Java中的反射
Java反射机制发生在运行时期,对于任意一个实体类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。反射一直被冠以"简单粗暴"的称号, 反射是暴力的, 也是很重要的, 众多框架的底层实现都用到了反射.
Class类
我们用类来描述对象, 比如有一个Animal类, 有三个对象: dog、bird、cat, 我们用Animal类来描述这三个对象; 有一个类Person, 有三个对象xiaoMing、xiaoHong、xiaoFang, 我们用Person类去描述这三个对象.
那问题来了, 在Java中, 一切都是对象, 类也可以理解为对象, 那我们该用什么来描述类呢?
就是Class类!
我们通过Class类来获取一个类的字节码对象, 得到它的字节码对象后, 你就可以随意操纵它, 你拥有它的最高权力, 这就好比是手机Root之后, 你就获得了操纵手机的最高权力
获取字节码对象的三种方式
假设有一个类如下
public class ReflectionDemo {
private static final String NAME = "Will"; //NAME是私有静态常量
}
方法一: Class.forName(“类的全限定名称”);
Class<?> clz = Class.forName("com.pac1.ReflectionDemo"); //得到ReflectionDemo类的字节码对象,这种方式最常用
方法二: 类名.class
Class<ReflectionDemo> clz= ReflectionDemo.class;
方法三: 对象名.getClass()
Class<? extends ReflectionDemo> clz= reflectionDemo.getClass();
附上修改static final字段的完整代码
public class ReflectionDemo {
private static final String NAME = "AAA"; //NAME是静态常量
}
class Test{
public static void main(String[] args) throws Exception{
//得到字节码对象
Class<?> clz = Class.forName("com.pac1.ReflectionDemo");
//获取变量名为"NAME"的私有字段
Field field = clz.getDeclaredField("NAME");
//无视private修饰符,暴力访问
field.setAccessible(true);
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
//去掉final修饰符
modifiers.setInt(field,field.getModifiers() & ~Modifier.FINAL);
System.out.println("修改前: "+ field.get(null));
field.set(null,"BBB");
System.out.println("修改后: "+field.get(null));
//再把final修饰符给加回来
modifiers.setInt(field,field.getModifiers() & ~Modifier.FINAL);
}
}
运行结果: