浅谈--Java反射
Java反射是什么?
Java反射是一种运行时能够动态获取类的信息并操作类的能力!(相当于上帝模式,巨屌)
Java反射的核心原理基于类加载机制和类的元数据。
类加载机制
Java类加载机制主要使用类加载器(ClassLoader)进行相应的类加载。ClassLoader主要使用loadClass()方法进行相应类的加载,遵循双亲委派原则。
如何避免类的重复加载呢?主要依靠的是synchronized和双亲委派机制!
1、synchronized保障了类加载时的线程安全。
2、双亲委派机制通过划分加载区间,先委托父类进行加载,父类无法加载再自己加载,保障了类不会重复加载。
如下把loadClass()方法源代码给剖出来。
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// 用synchronized保障线程安全
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
// 如下体现了双亲委派机制。
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
PerfCounter.getParentDelegationTime().addTime(t1 - t0);
PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
类的元数据
通过类加载器加载后就会生成一个Class对象。
Class对象存储类的字段、方法、构造器、父类、接口、注解等元数据。
Java反射的常见玩法
动态代理
原生JDK提供了基于Java反射的动态代理机制,使用Proxy来实现。
改变final修饰的常量值
public class ReflectionTest {
// TODO 改变这个num值!
private final int value;
public ReflectionTest(int value){
this.value = value;
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
ReflectionTest reflectionTest = new ReflectionTest(2);
System.out.println("没改变前:"+reflectionTest.value);
// 通过Class对象获取字段
Field field = reflectionTest.getClass().getDeclaredField("value");
field.setAccessible(true);
field.setInt(reflectionTest,10);
System.out.println("改变后:"+reflectionTest.value);
}
}
输出:
没改变前:2
改变后:10

浙公网安备 33010602011771号