首先要感谢下这位可爱的作者:
http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html。
本文是基于其模板的模仿实验。
获得Class 对象
public class Hello { public static void main(String[] args) { Weatherinfo weatherinfo = new Weatherinfo(); System.out.println(weatherinfo.getClass()); } }
在JVM 的某一节中我们已经有讲述,这里实际上得到的是这个类型的Class 类型的实例。
而Class 类型实例拥有读取Method Area 的能力。
获得实例化的Class对象的方式
public static void main(String[] args) { Class<?> demo1 = null; Class<?> demo2 = null; Class<?> demo3 = null; try { demo1 = Class.forName("mike.weather.model.Weatherinfo"); } catch (Exception e) { e.printStackTrace(); } demo2 = new Weatherinfo().getClass(); demo3 = Weatherinfo.class; System.out.println("class name: " + demo1); System.out.println("class name: " + demo2); System.out.println("class name: " + demo3); }
这里我们可以看到三种不同的方式:
1 直接按类的全限定名
2 类的实例
3 .class 其实是一种原始表达式的方式
通过Class获得实例化的能力
public static void main(String[] args) { Class<?> demo1 = null; try { demo1 = Class.forName("org.mike.reflect.Person"); } catch (Exception e) { e.printStackTrace(); } Person per = null; try { per = (Person) demo1.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } per.setName("Mike"); per.setAge(20); System.out.println(per); }
当去掉Person 类的默认无参构造函数之后,该代码就会报错。
java.lang.InstantiationException: org.mike.reflect.Person at java.lang.Class.newInstance(Unknown Source) at org.mike.reflect.Hello.main(Hello.java:17) Exception in thread "main" java.lang.NullPointerException at org.mike.reflect.Hello.main(Hello.java:24)
自带构造函数的实例化
public static void main(String[] args) { Class<?> demo = null; try { demo = Class.forName("org.mike.reflect.Person"); } catch (Exception e) { e.printStackTrace(); } Person per1 = null; Person per2 = null; Person per3 = null; Person per4 = null; Constructor<?> cons[] = demo.getConstructors(); try { per1 = (Person) cons[0].newInstance("Mike", 20); } catch (Exception e) { e.printStackTrace(); } System.out.println(per1); }
这个Constructor<?> 泛型数组里面的东东顺序是变动的。
返回某个类实现的接口
public static void main(String[] args) { Class<?> demo = null; try { demo = Class.forName("org.mike.reflect.Person"); } catch (Exception e) { e.printStackTrace(); } Class<?> intes[] = demo.getInterfaces(); for (int i = 0; i < intes.length; i++) { System.out.println("implements interface: " + intes[i]); } }
获取大集合
public static void main(String[] args) { Class<?> demo = null; try { demo = Class.forName("org.mike.reflect.Person"); } catch (Exception e) { e.printStackTrace(); } System.out.println("current class: "); Field[] field = demo.getDeclaredFields(); for (int i = 0; i < field.length; i++) { int mo = field[i].getModifiers(); String priv = Modifier.toString(mo); Class<?> type = field[i].getType(); System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";"); } System.out.println("interface or more: "); Field[] filed1 = demo.getFields(); for (int j = 0; j < filed1.length; j++) { int mo = filed1[j].getModifiers(); String priv = Modifier.toString(mo); Class<?> type = filed1[j].getType(); System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";"); } }
原文已经足够的详细,这里就不一一复制了。
接下去是,动态代理
先获得类型加载器:
package org.mike.reflect; public class Hello { public static void main(String[] args) { Person t = new Person(); System.out.println("current class loader: " + t.getClass().getClassLoader().getClass().getName()); } }
在JVM 的章节里面我们讲到有好几种类型加载器:
1 Bootstrap ClassLoader 引导用的
2 Extension ClassLoader 加载Applet 之类中的扩展用的
3 AppClassLoader 加载指定的Class, 比较常用
后面的几种其实都统称为用户自定义类型加载器。
package org.mike.reflect; public class Hello { public static void main(String[] args) { MyInvocationHandler demo = new MyInvocationHandler(); Subject sub = (Subject) demo.bind(new RealSubject()); String info = sub.say("Mike", 20); System.out.println(info); } }
这个据说是动态代理的实现,这个干嘛用啊,动态代理如雷贯耳,但是这里干嘛用啊不清楚。
类的生命周期
JVM 通过类型装载器加载类,将.class 文件中的二进制文件装入method area, 并在Heap 中创建这个java.lang.Class 对象的实例。
链接就是让二进制数据组装为可以运行的状态。
链接分为校验,准备和解析3个阶段。
校验一般验证是否适合当前JVM 版本。
准备就是为静态成员分配内存空间,和设置默认值。
解析就是转换常量池中的代码为直接引用的过程。
初始化完成后,类的对象就可以正常使用了。
当没有任何引用指向Class 对象时就会被卸载,结束类的生命周期。
动态代理
关于动态代理,要感谢另外的这个小伙伴:
http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html
首先代理模式这个东东不用多说了,按照代理的创建过程,分为静态代理和动态代理。
首先静态代理很简单,基本就是我原来对于代理模式的理解。
代理类和被代理类实现同样的接口,我们发现这样重复代码太多。
将所有的公共代码提取出来以后,我们只关心我们这么调用即可。
public Object bind(Object obj) { this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); }
public static void main(String[] args) { MyInvocationHandler demo = new MyInvocationHandler(); Subject sub = (Subject) demo.bind(new RealSubject()); String info = sub.say("Mike", 20); System.out.println(info); }
省下了很多公共的代码。
这个方法的取点是必须要实现一样的接口。
那没有接口怎么办呢?
cglib 对指定的目标生成子类,并覆盖其中的方法实现来实现动态代理。
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; }
具体的例子我没写,估计差不多理解这个原理就够忽悠人了,当真正遇到需要用的时候自然就会了。