(点击跳转即可哦)
反射
反射:
在JVM
运行时,
对于JVM中任何一个类,都能动态获取该类的所有属性和方法。
对于JVM中任何一个对象,都能动态调用该对象的属性和方法
动态获取信息以及调用对象机制称为 反射机制
反射基本信息
Java程序中许多对象在运行时会出现两种类型:运行时类型(RTTI)和编译时类型,
例如Person p = new Student();
这句代码中p在编译时类型为Person,运行时类型为Student。
运行时明确该引用到底是啥类型就可以通过反射机制。
反射相关的类
java.lang.reflect
包下的
类名 | 用途 |
---|---|
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量/类的属性 |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
Class类:反射核心类,使用Class关键字,包括数组,包括接口编译后生成的class文件就对于一个唯一的class对象,由JVM产生,使用这个class对象就可以获取该类的所有信息
Field类:反射调用类中的成员/类属性
Method类:反射调用类中的成员/类方法
Constructor类:反射调用构造方法
1 获取该类的class对象
1 无论要通过反射机制干啥事,首先第一步要获取该类的class对象(由JVM产生的,全局唯一)
a. 调用Class.forName
(类的全名称,包名.类名)
b. 调用类名称.class属性 eg:Student.class
c. 通过该类的任意对象的getClass
方法()
public class Test{
public static void main(String[] args) throw Exception{
//1 获取Student 类的class对象
Class<Student> c1 = (Class<Student>) class.forName("包名.类名");
//2 通过类名称.class 获取class
Class<Student> c2 = Student.class;
//3 通过Student对象的getClass方法
Class<Student> c3 = (Class<Student>) new Student().getClass();
}
}
Person per = new Student();
//通过反射 就可以看到他运行时类型 RTTI
System.out.println(per.getClass());
2 通过反射调用构造方法
以下方法返回值为 Constructor相关
//获得该类中参与类型匹配的公有构造方法
getConstructor(Class...<?> parameterTypes)
//获得该类的所有公有构造方法
getConstructors()
//获得该类中与参数类型匹配的构造方法
getDeclaredConstructor(Class...<?> parameterTypes)
//获得该类所有构造方法
getDeclaredConstructors()
普通的get 只能获取public权限的方法或者属性
getDeclared…()可以获取所有权限的方法或者属性
Class<Student> cls = Student.class;
//获得所有public权限的构造方法
Constructor[] constructors = cls.getConstructors();
//打印
for(Constructor constructor : constructors){
System.out.println(constructor);
}
//获得该类所有构造方法
Constructor[] cs = cls.getDeclaredConstructors();
//打印
for(Constructor constructor : cs){
System.out.println(constructor);
}
Class<Student> cls = Student.class;
//获取指定类型的有参构造
ConStructor<Student> constructor = cls.getDeclaredConstructor(String.class,String.class,int.class);
Students student = constructor.newInstance("姓名","性别",18);
System.out.println(student);
破坏封装产生对象
Class<Student> cls = Student.class;
//获取指定类型的有参构造
ConStructor<Student> constructor = cls.getDeclaredConstructor(String.class);
//破环封装,通过反射破坏private封装,调用私有构造方法
constructor.setAccessible(true);
Student student = constructor.newInstance("姓名");
System.out.println(student);
3 通过反射调用普通方法
以下方法返回值为 Method相关
//获得该类某个公有的方法
getMethod(String name, Class...<?> parameterTypes)
//获得该类所有公有的方法
getMethods()
//获得该类某个方法
getDeclaredMethod(String name, Class...<?> parameterTypes)
//获得该类所有方法
getDeclaredMethods()
通过Method类调用相应方法
public Object invoke(Object obj,Object... args)
第一个参数:通过哪个对象调用这个方法,普通方法必须通过对象调用,若是静态方法,这里传入null
第二个参数:要调用方法的具体参数
public static void test(){
System.out.println("Student类的静态方法")
}
Class<Student> cls = Student.class;
//获取调用方法的Method对象
Method method = cls.getDeclaredMethod(test);
//test就是静态方法,无须产生Student对象
method.invoke(null);
//输出结果:Student类的静态方法
public void fun(String msg){
System.out.println(this.name + "Student类的普通方法");
System.out.println(msg);
}
Class<Student> cls = Student.class;
Method method2 = cls.getDeclaredMethod("fun",String.class);
//产生Student对象
Student student = new Student("姓名","性别",18);
method2.invoke(student,"电脑修好了");
// 通过哪个对象调用的, 具体的参数
常用获得类中属性相关的方法
以下方法返回值为 Field相关
getField(String name) //获得某个公有的属性对象
getFields() //获得所有公有的属性对象
getDeclaredField(String name) //获得某个属性对象
getDeclaredFields() //获得所有属性对象
//Field类的方法
//通过obj对象获取相关属性的值,属性为静态属性时则传入null
public Object get(Object obj)
//通过obj对象修改相关属性的值
public void set(Object obj,Object value)
//获取要拿到的属性Field对象
Field field = cls.getDeclared("country");//静态
System.out.println(field.get(null));
Field field1 = cls.getDeclared("age");
Student student = new Student("姓名","性别",18);
System.out.println(field1.get(student)); //输出结果为 18
field1.set(student,20);
System.out.println(field.get(student));//输出结果是 20
要是对大家有所帮助的话,请帮我点个赞吧。