反射 顾名思义 就是反着来 正常的类创建是 new出来的 而反射是通过一个实例 去反着得到一个类 。
如果两个实例都是相同的类 new出来的 那个这两个类反射得到的 Class对象 也是一样的。(hashcode相同)
通过反射 我们可以得到这个类中的所有属性(不管是不是private的) 它的所有方法 它的一切 都可以通过反射得到。
创建一个类分为三个步骤 : 加载 链接 初始化
加载: 将Class字节码内容加载到内存中,然后生成一个 java.lang.Class对象
链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。
初始化: 当初始化一个类的时候 如果它的父类还未被初始化 那么会先初始化它的父类
反射的一些方法 代码如下:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class Test{
public String name;//public类型的属性
private int id;//private类型的属性
public Test(){
}
public Test(String name,int id){
this.id = id;
this.name = name;
}
//私有的方法
private void sayHi(){
System.out.println("Hi !");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Test t1 = new Test("哈宝欣",38);//使用普通的new 方法实例化对象
Class<?> c1 = Class.forName("Test");
//获得类的全名
System.out.println(c1.getName());
//获得类的所有构造方法(不管是不是private) 如果只想获得公开的构造方法 就使用c1.getConstructors()
Constructor[] constructors = c1.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//获得类的所有方法(不管是不是private)如果只想获得公开的方法 就使用c1.getMethods()
Method[] declaredMethods = c1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
//获得类的所有属性
Field[] declaredFields = c1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//可以使用反射得到的构造方法初始化一个对象
//首先先获得想要的构造函数
Constructor test = c1.getDeclaredConstructor(String.class,int.class);
//使用构造函数的newInstance方法 实例化一个对象
Test t2 = (Test)test.newInstance("李四",1);
System.out.println(t2.getName());
//可以使用反射得到普通方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//使用函数的invoke() 执行这个函数 参数分别是 执行这个函数的对象和传入这个函数的参数
setName.invoke(t2,"李思思");
System.out.println(t2.getName());
//可以通过反射去操作字段
//获得这个字段属性
Field id = c1.getDeclaredField("id");
//操作这个属性
System.out.println(t2.getId());
//使用set方法去操作这个属性 参数是操作的对象和传入的参数
// 注意 如果这个字段是私有的 那么要使用setAccessible方法 把它这设置为可以访问才能修改
id.setAccessible(true);
id.set(t2,989);
System.out.println(t2.getId());
}
}