快速了解Java反射
相信大家都知道反射的重要性,每个类的对象都可以通过反射构造出来,反射可以获取类的所有属性、方法。注解离不开反射机制,设计模式里面的动态代理也是依靠反射进行的,很多优秀框架都是在反射机制下完成的。
概念、理论再多都不如代码实在(有不对的地方,欢迎指出,同样也欢迎内容补充)。
先写一个Person类
public class Person {
private String name;
public int age;
public Person() {}
protected Person(String name) {
this.name = name;
}
private Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
System.out.println("获取姓名");
return name;
}
private void setName(String name) {
System.out.println("姓名写入中...");
this.name = name;
}
private void init(String name,int age){
System.out.println("进行初始化...");
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
一、获取Class对象的三种方式
1.对象调用getClass()方法
Class代表一个类,通过Class可以拿到对应类的属性及方法。
Person person = new Person();
Class<? extends Person> clazz = person.getClass();
2.对应类的静态属性class
Class<Person> clazz = Person.class;
3.调用Class类的静态方法forName(“详细路径”)
Class<?> clazz = Class.forName("com.***.demo.Person");
二、获取类的构造方法
Constructor代表构造方法
1、getDeclaredConstructors()方法获取所有构造函数,getConstructors()方法获取所有公有构造函数。
Class<?> clazz = Class.forName("com.***.demo.Person");
//获取所有的构造函数
Constructor<?>[] constructors0 = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructors0) {
System.out.println(constructor);
}
//打印结果
//private com.***.demo.Person(java.lang.String,int)
//protected com.***.demo.Person(java.lang.String)
//public com.***.demo.Person()
Constructor<?>[] constructors1 = clazz.getConstructors();
for (Constructor<?> constructor : constructors1) {
System.out.println(constructor);
}
//打印结果
//public com.***.demo.Person()
2、getConstructor(Class<?>... parameterTypes)获取公有构造函数,getDeclaredConstructor(Class<?>… parameterTypes)获取其他作用域的构造函数。
Class<?> clazz = Class.forName("com.***.demo.Person");
//公有构造函数的获取
Constructor<?> constructor = clazz.getConstructor();
Object obj = constructor.newInstance();
System.out.println(obj);
//打印结果
//Person{name='null', age=0}
//其他作用域的构造函数的获取
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
Object obj = constructor.newInstance("ZhangSan");
System.out.println(obj);
//打印结果
//Person{name='ZhangSan', age=0}
Class<?> clazz = Class.forName("com.huangwei.rpc.demo.Person");
//私有化的构造方法获取
//普通数据类型为对应包装类的TYPE
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class,Integer.TYPE);
constructor.setAccessible(true);//开启暴力反射
Object obj = constructor.newInstance("ZhangSan",18);
System.out.println(obj);
//打印结果
//Person{name='ZhangSan', age=18}
三、获取类的属性
1、getDeclaredFields()方法获取所有属性,getFields()获取所有公有属性。
Person person = new Person("ZhangSan");
person.age = 18;
Class<? extends Person> clazz = person.getClass();
//获取类的公有属性
Field[] fields0 = clazz.getDeclaredFields();
for (Field field : fields0) {
field.setAccessible(true);//开启暴力反射
System.out.println(field.get(person));
}
//打印结果
//ZhangSan
//18
//获取类的公有属性
Field[] fields1 = clazz.getFields();
for (Field field : fields1) {
System.out.println(field.get(person));
}
//打印结果
//18
2、getField(String name)获取公有属性进行操作,getDeclaredField(String name)获取其他属性进行操作。
Class<?> clazz = Class.forName("com.***.demo.Person");
Object obj = clazz.newInstance();
//通过反射操作public属性
Field field0 = clazz.getField("age");
field0.setInt(obj,28);
System.out.println(field0.get(person));
//打印结果
//28
//通过反射操作非公有属性
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);//开启暴力反射
field.set(obj,"LiSi"); //修改私有属性
System.out.println(field.get(obj)); //获取私有属性
//打印结果
//LiSi
四、获取类的方法
1、getDeclaredMethods()获取所有非构造方法(包括父类及接口的方法),getMethods()获取所有public非构造方法(包括父类及接口的方法)
Class<?> clazz = Class.forName("com.***.demo.Person");
Method[] methods0 = clazz.getMethods();
for (Method method : methods0) {
System.out.println(method.getName());
}
Method[] methods1 = clazz.getDeclaredMethods();
for (Method method : methods1) {
System.out.println(method.getName());
}
2、getDeclaredMethod(String name, Class<?>... parameterTypes)获取本对象的方法,getMethod(String name, Class<?>… parameterTypes)获取公有方法,第一个参数为方法名,第二个参数可变数组是参数类型,按照方法参数顺序进行定义
Class<?> clazz = Class.forName("com.***.demo.Person");
Object obj = clazz.newInstance();
//获取无参数的方法,第二个参数为可变数组,调用方法没有参数时,第二个参数可以省略不写
Method method0 = clazz.getMethod("getName");
method0.invoke(obj); //获取姓名
//获取基类Object下的方法
Method method1 = clazz.getMethod("equals", Object.class);
method1.invoke(obj, new Person()); //false
//获取私有化的方法
Method method3 = clazz.getDeclaredMethod("setName", String.class);
method3.setAccessible(true); //开启暴力反射
//调用私有方法
method3.invoke(obj,"ZhangSan"); //姓名写入中...
//多参数的方法,对应参数类型入参
Method method4 = clazz.getDeclaredMethod("init", String.class, int.class);
method4.setAccessible(true); //开启暴力反射
//调用私有方法
method4.invoke(obj,"ZhangSan",18); //进行初始化...
// method获取对象的Class(Constructor,Field 都有这个方法)
Class<?> aClass = method.getDeclaringClass();
反射在java.lang.reflect包下,反射影响性能,能直接实现就不用反射。