使用Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。
新建一个user类
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String name;
private Integer age;
private Integer salary;
String sex;
public String password;
public User(User user) {
}
private User(String name) {
this.name = name;
}
public void show1(String s) {
System.out.println("调用了:公有的,String参数的show1(): s = " + s);
}
protected void show2() {
System.out.println("调用了:受保护的,无参的show2()");
}
void show3() {
System.out.println("调用了:默认的,无参的show3()");
}
private String show4(int age) {
System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
return "show4";
}
- 获取class对象的三种方式
ClassuserClass1 = User.class; Class> userClass2 = Class.forName("com.example.demos.entity.User"); User user = new User(); Class extends User> userClass3 = user.getClass(); System.out.println("方式1:" + userClass1); System.out.println("方式2:" + userClass2); System.out.println("方式3:" + userClass3);
方式1:class com.example.demos.entity.User
方式2:class com.example.demos.entity.User
方式3:class com.example.demos.entity.User
- 通过反射构造一个类的实例
User user1 = userClass1.newInstance();
System.out.println("类的实例:" + user1);
类的实例:User(name=null, age=null, salary=null, sex=null, password=null)
- 获取所有公有构造方法
Constructor>[] constructors = userClass1.getConstructors();
System.out.println("所有的公有构造方法:" + Arrays.asList(constructors));
所有的公有构造方法:[public com.example.demos.entity.User(), public com.example.demos.entity.User(java.lang.String,java.lang.Integer,java.lang.Integer,java.lang.String,java.lang.String), public com.example.demos.entity.User(com.example.demos.entity.User)]
- 获取所有的构造方法(包括:私有、受保护、默认、公有)
Constructor>[] declaredConstructors = userClass1.getDeclaredConstructors();
System.out.println("所有的构造方法:" + Arrays.asList(declaredConstructors));
所有的公有构造方法:[public com.example.demos.entity.User(), public com.example.demos.entity.User(java.lang.String,java.lang.Integer,java.lang.Integer,java.lang.String,java.lang.String), public com.example.demos.entity.User(com.example.demos.entity.User)]
- 获取公有构造方法
Constructorconstructor = userClass1.getConstructor(); System.out.println("公有构造方法:" + constructor);
公有构造方法:public com.example.demos.entity.User()
- 获取私有构造方法
ConstructordeclaredConstructor = userClass1.getDeclaredConstructor(String.class); System.out.println("私有构造方法:" + declaredConstructor);
私有构造方法:private com.example.demos.entity.User(java.lang.String)
- 开源库 Objenesis 可以调用任意的构造函数
Objenesis objenesis = new ObjenesisStd(true);
User user2 = objenesis.newInstance(User.class);
System.out.println("Objenesis:" + user2.toString());
Objenesis:User(name=null, age=null, salary=null, sex=null, password=null)
- 获取所有公有的字段
Field[] fields = userClass2.getFields();
System.out.println("获取所有公有的字段: " + Arrays.toString(fields));
获取所有公有的字段: [public java.lang.String com.example.demos.entity.User.password]
- 获取所有私有的字段
Field[] declaredFields = userClass2.getDeclaredFields();
System.out.println("获取所有私有的字段: " + Arrays.toString(declaredFields));
获取所有私有的字段: [private java.lang.String com.example.demos.entity.User.name, private java.lang.Integer com.example.demos.entity.User.age, private java.lang.Integer com.example.demos.entity.User.salary, java.lang.String com.example.demos.entity.User.sex, public java.lang.String com.example.demos.entity.User.password]
- 获取指定共有字段
Field publicName = userClass2.getField("password");
System.out.println("获取指定共有字段: " + publicName);
获取指定共有字段: public java.lang.String com.example.demos.entity.User.password
- 获取指定私有字段
Field declaredName = userClass2.getDeclaredField("name");
System.out.println("获取指定私有字段: " + declaredName);
获取指定私有字段: private java.lang.String com.example.demos.entity.User.name
- 获取所有公有方法
Method[] methods = userClass3.getMethods();
System.out.println("获取所有公有方法: " + Arrays.toString(methods));
获取所有公有方法: [public boolean com.example.demos.entity.User.equals(java.lang.Object), public java.lang.String com.example.demos.entity.User.toString(), public int com.example.demos.entity.User.hashCode(), public java.lang.String com.example.demos.entity.User.getName(), public void com.example.demos.entity.User.setName(java.lang.String), public java.lang.String com.example.demos.entity.User.getPassword(), public void com.example.demos.entity.User.show1(java.lang.String), public java.lang.String com.example.demos.entity.User.getSex(), public static com.example.demos.entity.User$UserBuilder com.example.demos.entity.User.builder(), public java.lang.Integer com.example.demos.entity.User.getSalary(), public void com.example.demos.entity.User.setSalary(java.lang.Integer), public void com.example.demos.entity.User.setPassword(java.lang.String), public java.lang.Integer com.example.demos.entity.User.getAge(), public void com.example.demos.entity.User.setAge(java.lang.Integer), public void com.example.demos.entity.User.setSex(java.lang.String), public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
- 获取所有私有方法
Method[] declaredMethods = userClass3.getDeclaredMethods();
System.out.println("获取所有私有方法: " + Arrays.toString(declaredMethods));
获取所有私有方法: [public boolean com.example.demos.entity.User.equals(java.lang.Object), public java.lang.String com.example.demos.entity.User.toString(), public int com.example.demos.entity.User.hashCode(), public java.lang.String com.example.demos.entity.User.getName(), public void com.example.demos.entity.User.setName(java.lang.String), public java.lang.String com.example.demos.entity.User.getPassword(), public void com.example.demos.entity.User.show1(java.lang.String), private java.lang.String com.example.demos.entity.User.show4(int), public java.lang.String com.example.demos.entity.User.getSex(), protected void com.example.demos.entity.User.show2(), public static com.example.demos.entity.User$UserBuilder com.example.demos.entity.User.builder(), public java.lang.Integer com.example.demos.entity.User.getSalary(), public void com.example.demos.entity.User.setSalary(java.lang.Integer), public void com.example.demos.entity.User.setPassword(java.lang.String), public java.lang.Integer com.example.demos.entity.User.getAge(), public void com.example.demos.entity.User.setAge(java.lang.Integer), protected boolean com.example.demos.entity.User.canEqual(java.lang.Object), void com.example.demos.entity.User.show3(), public void com.example.demos.entity.User.setSex(java.lang.String)]
- 获取指定共有方法
Method show1 = userClass3.getMethod("show1", String.class);
System.out.println("获取指定共有方法: " + show1);
获取指定共有方法: public void com.example.demos.entity.User.show1(java.lang.String)
- 共有方法调用
show1.invoke(user1, "我这个是参数");
调用了:公有的,String参数的show1(): s = 我这个是参数
- 获取指定私有方法
Method show4 = userClass3.getDeclaredMethod("show4", int.class);
System.out.println("获取指定私有方法: " + show4);
获取指定私有方法: private java.lang.String com.example.demos.entity.User.show4(int)
- 私有方法调用
// 解除私有限定
show4.setAccessible(true);
Object invoke = show4.invoke(user1, 18);
System.out.println("show4的返回值: " + invoke);
通过反射实现bean的copy调用了,私有的,并且有返回值的,int参数的show4(): age = 18
show4的返回值: show4
public static Object copy(Object object) throws Exception {
//获得对象的类型
Class> classType = object.getClass();
System.out.println("Class: " + classType.getName());
//通过默认构造方法创建一个新的对象
Object objectCopy = classType.newInstance();
//获得对象的所有属性
Field[] fields = classType.getDeclaredFields();
for (Field field : fields) {
String fieldName = field.getName();
String firstLetter = fieldName.substring(0, 1).toUpperCase();
//获得和属性对应的getXXX()方法的名字
String getMethodName = "get" + firstLetter + fieldName.substring(1);
//获得和属性对应的setXXX()方法的名字
String setMethodName = "set" + firstLetter + fieldName.substring(1);
//获得和属性对应的getXXX()方法
Method getMethod = classType.getMethod(getMethodName);
//获得和属性对应的setXXX()方法
Method setMethod = classType.getMethod(setMethodName, field.getType());
//调用原对象的getXXX()方法
Object value = getMethod.invoke(object);
System.out.println(fieldName + ":" + value);
//调用拷贝对象的setXXX()方法
setMethod.invoke(objectCopy, value);
}
return objectCopy;
}
Test
public static void main(String[] args) throws Exception {
User user = User.builder()
.name("张三")
.age(18)
.build();
User user1 = (User) copy(user);
System.out.println(user1);
}
Class: com.example.demos.entity.User
name:张三
age:18
salary:null
sex:null
password:null
User(name=张三, age=18, salary=null, sex=null, password=null)



