Java 反射总结
类装载器工作机制
类装载器就是寻找类的节码文件并构造出类在JVM 内部表示对象的组件。在Java 中,
类装载器把一个类装入JVM 中,要经过以下步骤:
1.装载:查找和导入Class 文件;
通过一个类的全限定名来获取定义此类的二进制字节流.然后将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构.最后在Java堆中生成一个代表这个类的java.lang.class对像,作为方法区的数据入口.
2.链接:执行校验、准备和解析步骤,其中解析步骤是可以选择的:
a)校验:检查载入Class 文件数据的正确性;
b)准备:给类的静态变量分配存储空间;
c)解析:将符号引用转成直接引用;
3.初始化:对类的静态变量、静态代码块执行初始化工作。
类装载工作由ClassLoader 及其子类负责,ClassLoader 是一个重要的Java 运行时系统组件,它负责在运行时查找和装入Class 字节码文件。JVM 在运行时会产生三个
ClassLoader:
BootstrapClassLoader
Extension ClassLoader(扩展类装载器)
Application ClassLoader(系统类装载器)。
其中,BootstrapClassLoader不是ClassLoader 的子类,它使用C++编写,因此我们在Java 中看不到它,BootstrapClassLoader负责装载JRE 的核心类库,如JRE 目标下的rt.jar、charsets.jar 等。
Extension ClassLoader 和Application ClassLoader 都是ClassLoader 的子类。其中Extension ClassLoader 负责装载 JRE 扩展目录ext 中的JAR 类包;Application 负责装载Classpath 路径下的类包。
getParent() |
返回该类加载器的父类加载器。 |
loadClass(String name) |
加载名称为 name 的类,返回的结果是 java.lang.Class 类的实例。 |
findClass(String name) |
查找名称为 name 的类,返回的结果是 java.lang.Class 类的实例。 |
findLoadedClass(String name) |
查找名称为 name 的已经被加载过的类,返回的结果是 java.lang.Class 类的实例。 |
defineClass(String name, byte[] b, int off, int len) |
把字节数组 b 中的内容转换成 Java 类,返回的结果是 java.lang.Class 类的实例。这个方法被声明为 final 的。 |
resolveClass(Class<?> c) |
链接指定的 Java 类。 |
public class ClassLoaderTest { public static void main(String[] args) { ClassLoader loader = Thread.currentThread().getContextClassLoader(); System.out.println("current loader:"+loader); System.out.println("parent loader:"+loader.getParent()); System.out.println("grandparent loader:"+loader.getParent(). getParent()); } }
current loader:sun.misc.Launcher$AppClassLoader@131f71a parent loader:sun.misc.Launcher$ExtClassLoader@15601ea //①根装载器在Java中访问不到,所以返回null grandparent loader:null
获取当前线程的ClassLoader:
ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class.getClassLoader() ;实例化Class类对象的三种方式:
Class.forName("Reflect.Demo"); new Demo().getClass(); Demo.class;Class.forName(className)实际上是调用Class.forName(className, true, this.getClass().getClassLoader())。注意第二个参数,是指Class被loading后是不是必须被初始化。
Class<?> demo=Class.forName("Reflect.Person"); Constructor<?> cons[]=demo.getConstructors(); Object object = cons[0].newInstance(args);通过Class实例化接口
Class<?> intes[]=demo.getInterfaces();取得其他类中的父类
Class<?> superClass=demo.getSuperclass();
demo = Class.forName("Reflect.Demo"); Method method=demo.getMethod("toString"); method.invoke(demo.newInstance()); Method[] methods = demo.getDeclaredMethods();通过反射操作属性:
Field field = demo.getDeclaredField("sex"); field.setAccessible(true); field.set(obj, "男"); Field[] fields = Demo.class.getDeclaredFields(); //类中任何可见性的属性不包括基类 fields = Demo.class.getFields(); //只能获得public属性包括基类的使用数组
Class string = Class.forName("java.lang.String"); Object object= Array.newInstance(string, 10); Array.set(object, 5, "this is a test"); String s = (String) Array.get(arr, 5);
public class MyHandler implements InvocationHandler { private Object target; public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("事物开始"); Object result = method.invoke(target, args); System.out.println("事物结束"); return result; } }Cglib动态代理
public class MyCglib implements MethodInterceptor { private Object target; public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } @Override // 回调方法 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("事物开始"); proxy.invokeSuper(obj, args); System.out.println("事物结束"); return null; } }