Android Coder带你了解反射
前言
一般情况下,在使用某个类时必定清楚是什么类,作用是什么。使用时就直接对类进行实例化,调用对象进行操作。但在部分场景下开发时,开始并不知道操作类具体是什么,在运行时才知道具体类,并需要调用其方法,这就要使用反射来获取目标类的构造器,创建对应类对象,调用对应方法。
本篇就来说说反射知识。
概览
Class类
Class封装了当前对象所对应的类信息,每一个普通类都可以看成一个对象,是 java.lang.Class 类的对象,Class是描述类的类(有点拗口)
获取Class对象
有3种获取Class对象的方式:
- 通过类名获取=> 类名.class
- 通过对象名获取=> 对象名.getClass()
- 通过全类名获取=> Class.forName(全类名) //类全名:加上包名路径 如:com.any.bean.User
User user = new User(); // 正常 new关键字创建
Class userClass = User.class; // 类名.class
User userClass1 = user.getClass(); // 对象名.getClass()
Class userClass2 = Class.forName("com.any.bean.User");
创建实例
反射方式生成对象的实例:
Class userClass = User.class; // 获取到目标类
User user = (User) userClass.newInstance(); // 获取到实例
获取构造器
获取构造器的方式:
- Constructor getConstructor(Class[] params)获得使用指定参数类型的public构造函数
- Constructor[] getConstructors():获得类所有公共构造函数
- Constructor getDeclaredConstructor(Class[] params):获得使用特定参数类型的构造函数(包括私有)
- Constructor[] getDeclaredConstructors():获得类的所有构造函数
新建一个 Person
类,有私有属性和方法:
public class Person {
public String name;
private int age;
... // 省略掉 getter/setter
public Person() { // 无参公有构造器
super();
}
public Person(String name, int age) { //
this.name = name;
this.age = age;
}
private void privateMethod(){
System.out.println("the private method!");
}
}
新建GetConstructor
类来获取构造器:
public class GetConstructor {
public static void main(String[] args) throws Exception{
String className = "com.any.bean.Person";
Class<Person> personClass = (Class<Person>) Class.forName(className);
//获取全部公有constructor
Constructor<?>[] constructors = personClass.getConstructors();
for (Constructor<?> constructor: constructors) {
System.out.println("获取到公有constructor: " + constructor);
}
//获取指定constructor
Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
System.out.println("获取指定参数类型的constructor: " + constructor);
//调用构造器 newInstance() 方法创建对象
Person person = constructor.newInstance("Any", 27);
System.out.println(person.getName() + ", " + person.getAge() );
}
}
输出结果:
获取到公有constructor: public com.any.bean.Person(java.lang.String, int)
获取到公有constructor: public com.any.bean.Person()
获取指定参数类型的constructor: public com.any.bean.Person(java.lang.String, int)
any, 27
获取方法
获取方法有如下方式:
- Method getMethod(String name, Class[] params):使用特定的参数类型,获得命名的公共方法
- Method[] getMethods():获取类所有公共方法
- Method getDeclaredMethod(String name, Class[] params):通过指定参数类型,获取类声明方法
- Method[] getDeclaredMethods():获得类声明方法
用GetMethod
获取和调用方法:
public class GetMethod {
public static void main(String[] args) throws Exception{
Class<?> aClass = Class.forName("com.any.bean.Person");
//获取所有方法(不包含父类方法)
methods = aClass.getDeclaredMethods();
for (Method method: methods) {
System.out.println("获取到方法: " + method.getName() + "()");
}
System.out.println(“===========================”);
//获取指定的方法
Method method = aClass.getDeclaredMethod("setAge", int.class);
System.out.println("获取指定的方法:" + method);
//调用方法
Object instance = aClass.newInstance();
method.invoke(instance, 66);
//调用私有方法
method = aClass.getDeclaredMethod("privateMethod");
method.setAccessible(true); // 需要调用此方法且设置为 true
method.invoke(instance);
}
}
运行结果,如下:
获取到方法: getName()
获取到方法: setName()
获取到方法: setAge()
获取到方法: privateMethod()
获取到方法: getAge()
===========================
获取指定的方法:public void com.any.bean.Person.setAge(int)
set age: 66
the private method!
获取成员变量
获取成员变量的方式:
- Field getField(String name):获取指定名称的公共字段
- Field[] getFields():获取所有公共字段
- Field getDeclaredField(String name)`:获取类声明命名字段
- `Field[] getDeclaredFields():获取类声明所有字段
用 GetField
获取成员变量:
public class GetField {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.any.bean.Person");
// 获取所有字段(不包含父类字段)
Field[] fields = aClass.getDeclaredFields();
for (Field field: fields) {
System.out.println("获取的字段: " + field.getName());
}
System.out.println(“================”);
// 获取指定字段
Field name = aClass.getDeclaredField(“name”);
System.out.println("获取指定的字段: " + name.getName());
// 设置指定字段的值
Object instance = aClass.newInstance();
name.set(instance, "Any");
// 获取指定字段的值
Object o = name.get(instance);
System.out.println("获取指定字段的值: " + o);
}
}
运行结果:
获取的字段: name
获取的字段: age
================
获取指定的字段: name
获取指定字段的值: Any
总结
Java 反射机制主要提供:
- 运行时构造一个类的对象
- 运行时获取任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法(属性)
转载自:https://juejin.cn/post/7151389797993414693