关于java反射的笔记

来源:互联网 发布:c语言compare()函数 编辑:程序博客网 时间:2024/06/06 00:06

类加载器:

从java开发人员角度来看,类加载器包括以下几种:

  1. 启动(Bootstrap)类加载器:负责将 Java_Home/lib下面的类库加载到内存中(比如rt.jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。该类加载器由c/c++编写,通过getClassLoader()获取类加载器引用为空值null.
  2. 标准扩展(Extension)类加载器:是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将Java_Home /lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
  3. 应用程序(Application)类加载器:是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的.它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中.由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,因此一般称为系统(System)加载器.负责加载用户类路径定义的类库.可以通过Class.getSystemClassLoader()或自己编写的类.getClassLoader()来获取,一般自己没有定义别的类加载器,这个就是默认类加载器.

双亲委派模型:

                                                            
        双亲委派模型的工作过程:类加载器在收到类加载的请求后将请求委托给自己的父加载器(!!!!!非继承,通过getParent()方法获取父加载器),一层一层往上传,直到启动类加载器.当父加载器无法处理该请求时,子加载器才会自己处理这个请求.因为判断两个类是否相等不仅与类自己的定义有关,还与加载该类的类加载器有关,同一个类由不同的类加载器加载,会被判断为不同的类.通过双亲委派模型可以避免这种情况.
public class Test {public static void main(String[] args) {ClassLoader c = Test.class.getClassLoader();while (c != null) {System.out.println(c.getClass().getName());c = c.getParent();}}}
这段代码通过getParent()方法迭代获取了类加载器,因为启动类加载器获取为null,所以看不到启动类加载器.


反射就是由用户主动在运行期间动态加载类的一种机制.主要用到了java.lang.Class和java.lang.ClassLoader以及java.lang.reflect.*来实现反射.通过反射可以通过配置文件来动态加载类,还可以破坏类的封装性访问类的私有属性和私有方法.
import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Test {public static void main(String[] args) {try {Class c = Thread.currentThread().getContextClassLoader().loadClass("rTest");//Class c = Class.forName("rTest");Object rtest = c.newInstance();Method[] methods = c.getMethods();Field[] fields = c.getFields();for (Method m : methods) {//System.out.println(m);if (m.getName().equals("c")) {m.invoke(rtest, new Object[]{});} if (m.getName().equals("d")) {m.invoke(rtest, new Object[]{3, 4});} }for (Field f : fields) {System.out.println(f.get(rtest));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class  rTest{public int a = 0;private int b = 0;public void c() {System.out.println("c");}public void d(int a, int b) {this.a = a;this.b = b;System.out.println(a + b);}private void e() {System.out.println("e");}}


这是一个反射的简单例子,可以通过ClassLoader的loadClass()方法和Class.forName()来加载类.使用Class的getMethods()和getField()方法来获取方法和属性,但是这样不能获取私有的方法和属性,要获取私有的方法和属性,要用getDeclaredMethods()和getDeclaredField()来获取.关于其他的用法可以看api文档.


0 0
原创粉丝点击