一、简介
定义:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
面试经常问:如何在一个类中访问另一个类的私有方法或属性?
答:1.通过几种方式获得类对象,然后通过getDeclaredField()获取Field对象,再设置字段对象的setAccessible(true),最后设置通过get/set来获取、设置字段值。
2.通过几种方式获得类对象,然后通过getDeclaredMethod()获取Method对象,在设置(方法对象的setAccessible(true),最后用调用invoke()方法调用该方法(需要传参指定类对象实例和方法参数Obj[]数组)
需要了解这4个对象:
类名用途
Class类 代表类的实体,在运行的Java应用程序中表示类和接口
Field类 代表类的成员变量(成员变量也称为类的属性)
Method类 代表类的方法
Constructor类 代表类的构造方法
二、实例
话不多少,撸代码了
1.定义一个含有私有方法和属性的类
package com.naland.yc.demo.test.reflect;
public class ReflecTest {
private String name;
private int age;
private void getPerson(String name,int age){
System.out.println("姓名:"+name+ " 年龄:"+age);
}
public void pubGetPerson(){
System.out.println("公有方法访问 "+"姓名:"+name+ " 年龄:"+age);
}
private ReflecTest(String name, int age) {
this.name = name;
this.age = age;
}
public ReflecTest(){
}
@Override
public String toString() {
return "ReflecTest{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.反射调用实例
package com.naland.yc.demo.test.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTest2 {
public static void main(String[] args) {
//new一个对象
ReflecTest test = new ReflecTest();
/**
* 获取Class对象
*/
//方式1 实例.getClass()
Class test1 = test.getClass();
//方式2 Class.forName("com.naland.yc.demo.test.reflect.ReflectTest")
Class test2 = null;
try {
test2 = Class.forName("com.naland.yc.demo.test.reflect.ReflecTest");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//方式3 类名.class
Class test3 = ReflecTest.class;
//类对象获取实例
try {
ReflecTest test1Instance = (ReflecTest) test1.newInstance();
ReflecTest test2Instance = (ReflecTest) test2.newInstance();
ReflecTest test3Instance = (ReflecTest) test3.newInstance();
test1Instance.pubGetPerson();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//访问私有属性
Field field = null;
try {
field = test1.getDeclaredField("name");
field.setAccessible(true);
//此处需要传入实例对象
System.out.println(field.get(test));
field.set(test, "naland");
test.pubGetPerson();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//访问私有方法
Method method = null;
try {
//需要传入方法名和参数类型的class
method = test2.getDeclaredMethod("getPerson",new Class[]{String.class,int.class});
method.setAccessible(true);
method.invoke(test, new Object[]{"张三", 25});
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//访问私有构造方法
Constructor constructor=null;
try {
constructor=test3.getDeclaredConstructor(new Class[]{String.class,int.class});
constructor.setAccessible(true);
Object testInstance=constructor.newInstance(new Object[]{"Kobe Brant",38});
ReflecTest newInstance= (ReflecTest) testInstance;
System.out.println(newInstance.toString());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}