反射的定义
将类的各个组成部分封装成对象,这就是反射机制;或者说是在运行过程中动态获取类,调用方法。
下图是关于类加载的过程
类从编写到创建对象运行分为三个阶段
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());
}
}
@Override
public 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);
}
}