目录
一、什么是反射
反射:能够获取类信息的能力叫做反射
Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到类对象之后,再通过类对象进行反编译,从而获取对象的各种信息。
Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
二、反射的工作流程
public class Test {
public static void main(String[] args) throws Exception {
//磁盘阶段
Class class1 = Class.forName("反射.Student");
//类对象阶段
Class class2 = Student.class;
//运行时阶段
Student student = new Student();
Class class3 = student.getClass();
System.out.println(class1 == class2);
System.out.println(class2 == class3);
}
} //运行结果为true true
通过代码我们可以看到类信息在同一个地方
想要获取类信息就必须进入类对象阶段
三、用法
1、获取变量信息
getDeclaredFields()与getFields() 多个
getDeclaredField()与getField() 单个
加declare和不加的区别:加了declare能找到全部,不加declare仅能找到public修饰的
举例:创建student类
public class Student {
private String name = "nihao";
public int age;
Character sex = '男';
protected Double height = 180.0;
public String color = "blue";
}
测试类
public class Test {
public static void main(String[] args) throws Exception {
Class class1 = Class.forName("反射.Student");
//获取全部全局变量的信息,并打印
Field[] files = class1.getDeclaredFields();
System.out.println(Arrays.toString(files));
//获取public修饰的全局变量信息,并打印
Field[] files1 = class1.getFields();
System.out.println(Arrays.toString(files1));
System.out.println("------------------------");
//加declare
Field nameField =class1.getDeclaredField("name");
System.out.println(nameField);
Field heightField = class1.getDeclaredField("height");
System.out.println(heightField);
Field ageField = class1.getDeclaredField("age");
System.out.println(ageField);
//不加declare
Field nameField1 =class1.getField("name");
System.out.println(nameField1); //报错,pirvate不能访问
Field heightField1 = class1.getField("height");
System.out.println(heightField1); //报错,protected不能访问
Field ageField1 = class1.getField("age");
System.out.println(ageField1); //正确
}
}
运行结果
2、获取方法信息
getDeclaredMethods()与getMethods()
getDeclaredMethod()
测试类
public class Test {
public static void main(String[] args) throws Exception {
Class class1 = Class.forName("反射.Student");
Method[] declaredmethods = class1.getDeclaredMethods();
System.out.println(Arrays.toString(declaredmethods));
Method[] methods = class1.getMethods(); //包括了父类object类当中public修饰的方法
System.out.println(Arrays.toString(methods));
Method getage = class1.getDeclaredMethod("getage", int.class);
System.out.println(getage);
Method aaa = class1.getDeclaredMethod("aaa", String.class, Integer.class);
System.out.println(aaa);
Method run = class1.getDeclaredMethod("run");
System.out.println(run);
Method hhh = class1.getDeclaredMethod("haha", String.class, int.class);
Method run1 = class1.getMethod("run");
System.out.println(run1);
}
}
运行结果
3、获取构造器信息
getDeclaredConstructors()与getConstructors()
getDeclaredConstructor()
public class Test {
public static void main(String[] args) throws Exception {
Class class1 = Class.forName("反射.Student");
//获取public
Constructor[] constructors = class1.getConstructors();
System.out.println(Arrays.toString(constructors));
//获取全部
Constructor[] declareconstructors = class1.getDeclaredConstructors();
System.out.println(Arrays.toString(declareconstructors));
//单个获取,输入参数列表
Constructor a0 = class1.getDeclaredConstructor(); //
System.out.println(a0); //获取无参构造器
Constructor a1 = class1.getDeclaredConstructor(String.class,Integer.class);
System.out.println(a1); //获取有string和integer的构造器
Constructor a2 = class1.getDeclaredConstructor(String.class,Integer.class, Character.class, Double.class, String.class);
System.out.println(a2); //获取
}
}
运行结果
4、创建对象
newInstance(参数)
public static void main(String[] args) throws Exception {
Class class1 = Class.forName("反射.Student");
Constructor declaredconstructor = class1.getDeclaredConstructor(String.class,Integer.class);
//创建对象
Student student = (Student) declaredconstructor.newInstance("aaa",18);
Constructor declaredconstructor1 = class1.getDeclaredConstructor();
//private修饰的变量想要使用必须暴力反射
declaredconstructor1.setAccessible(true);
Student student2 = (Student) declaredconstructor1.newInstance();
}
}
5、调用方法
先获取方法,在调用方法(需要有对象)
方法名.invoke(对象,参数)
调用private方法需要暴力反射 .setAccessible(true);
创建student类
public class Student {
private String name = "nihao";
public Integer age;
Character sex = '男';
protected Double height = 180.0;
public String color = "blue";
//方法
public void run(){
System.out.println("run()");
};
private int getage(int age){
System.out.println("getage()");
return age;
}
void aaa(String name,Integer height){
System.out.println("aaa()");
}
protected void haha(String name,int age){
System.out.println("haha()");
}
}
测试类
public class Test {
public static void main(String[] args) throws Exception {
Class class1 = Class.forName("反射.Student");
Constructor declaredconstructor = class1.getDeclaredConstructor(String.class,Integer.class);
//创建对象
Student student = (Student) declaredconstructor.newInstance("aaa",18);
Method run = class1.getDeclaredMethod("run");
run.invoke(student);
Method getage = class1.getDeclaredMethod("getage", int.class);
getage.setAccessible(true);
getage.invoke(student,18);
Method aaa = class1.getDeclaredMethod("aaa", String.class, Integer.class);
aaa.invoke(student,"admin",1999);
Method haha = class1.getDeclaredMethod("haha", String.class, int.class);
haha.invoke(student,"admin",19);
}
}
运行结果
6、调用变量(get set)
public static void main(String[] args) throws Exception {
Class class1 = Class.forName("反射.Student");
Constructor declaredconstructor = class1.getDeclaredConstructor(String.class,Integer.class);
//创建对象
Student student = (Student) declaredconstructor.newInstance("aaa",18);
//private需要暴力反射
Field name = class1.getDeclaredField("name");
name.setAccessible(true);
name.set(student,"李四");
System.out.println(name.get(student));
Field age = class1.getDeclaredField("age");
age.set(student,88);
System.out.println(age.get(student));
Field sex = class1.getDeclaredField("sex");
sex.set(student,'女');
System.out.println(sex.get(student));
Field height = class1.getDeclaredField("height");
height.set(student,179.9);
System.out.println(height.get(student));
}
运行结果