关于java反射的笔记

    xiaoxiao2021-03-25  88

    类加载器:

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

    启动(Bootstrap)类加载器:负责将 Java_Home/lib下面的类库加载到内存中(比如rt.jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。该类加载器由c/c++编写,通过getClassLoader()获取类加载器引用为空值null.标准扩展(Extension)类加载器:是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将Java_Home /lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。应用程序(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 block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.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文档.
    转载请注明原文地址: https://ju.6miu.com/read-15936.html

    最新回复(0)