反射的定义
将类的各个组成部分封装成对象,这就是反射机制;或者说是在运行过程中动态获取类,调用方法。
下图是关于类加载的过程
类从编写到创建对象运行分为三个阶段
1)源代码编译阶段 通过编译器将.java文件编译成.class文件;
2)类对象阶段 通过类加载器将 .class文件加载到内存 然后通过反射将类的成员变为对象的形式;
3)运行阶段 new 了一个对象在堆中分配了地址,这个过程叫作类的运行时阶段。
反射的好处
在类的运行时可以动态的知道对象的信息。只需要拿到类的Class对象
获取Class对象的三种方式
1、Class.forName(“全类名”) 全类名=包名+类名 应用场景多用于配置文件 传入一个字符串路径
2、类名.class 多用于参数传递 比如锁 传入要锁的对象;
3、对象,getClass() 当知道对象是啥可以 通过对象的getClass()对象的getClass()方法获取类对象。
通过反射获取类的父类和其所有实现的接口
1、第一步获取类对象信息;
2、调用getInterfaces()方法获取。
代码如下
public class TestReflectDemo2 implements Serializable,Runnable {public static void main(String[] args) throws ClassNotFoundException {Class<?> class3 = null;class3 = Class.forName("reflect.TestReflectDemo2");//第二步 通过 类对象的 getSuperclass(); 获取该类的父类Class<?>[] interfaces = class3.getInterfaces();for (Class<?> anInterface : interfaces) {System.out.println(anInterface.getName());}}@Overridepublic void run() {}}
通过反射获取类所有的构造获取属性类似
1、先拿到类的Class类对象信息;
2、通过调用getConstructors()方法获取类所有的构造
代码如下
public class TestReflectDemo3 {public static void main(String[] args) throws Exception{//通过反射实例化Student对象Class<?> class1 = Class.forName("reflect.Student");Student student =(Student)class1.newInstance();student.setName("张三");System.out.println(student);//通过反射获取所有的构造Constructor<?>[] constructors = class1.getConstructors();for (Constructor<?> constructor : constructors) {for (int i = 0; i < constructor.getParameterTypes().length; i++) {if(i==constructor.getParameterTypes().length-1){//获取构造的参数类型System.out.println(constructor.getParameterTypes()[i].getName());}else {System.out.print(constructor.getParameterTypes()[i].getName()+",");}}}//调用构造返回一个对象Student student1 = (Student) constructors[0].newInstance("李松",13);System.out.println(student1);}}
通过反射获取类所有的方法并执行方法
1、获取类的Class对象;
2、通过class对象调用getMethod()方法返回一个Method对象数组,通过该数组拿到方法信息;
3、方法名.invoke()方法调用方法 需要传入调用的对象 。
package reflect;import java.lang.reflect.Method;import java.lang.reflect.Modifier;public class TestReflectDemo5 {public static void main(String[] args)throws Exception {Class<?> class1 = Class.forName("reflect.TestReflectDemo5");//获取类的所有方法Method[] methods = class1.getMethods();for (int i = 0; i < methods.length; i++) {//获取方法权限修饰符int temp = methods[i].getModifiers();Class<?>[] para = methods[i].getParameterTypes();//获取方法返回值Class<?> returnType = methods[i].getReturnType();// System.out.println("方法名: "+methods[i].getName()+" "+"返回值类型: "+returnType.getName()+" "+ Modifier.toString(temp) + " ");for (int j = 0; j < para.length; ++j) {System.out.print(para[j].getName() + " " + "arg" + j);if (j < para.length - 1) {System.out.print(",");}}}}}
package reflect;import java.lang.reflect.Method;/*** 通过反射机制调用某个类的方法*/public class TestReflectDemo6 {public static void main(String[] args) throws Exception{Class<?> class1 = Class.forName("reflect.TestReflectDemo6");//通过反射机制调用方法//得到一个Method对象 调用没有参数的方法Method fun1 = class1.getMethod("fun1");//调用方法 传入调用者fun1.invoke(class1.newInstance());//调用有参数的方法 一定得指明传入参数的class信息Method fun2 = class1.getMethod("fun2",String.class,int.class);fun2.invoke(class1.newInstance(),"张三",12);}public void fun1(){System.out.println("通过反射机制调用该方法");}//定义有参数的方法public void fun2(String name ,int age){System.out.println(name+age);}}
