类加载机制与反射
1 系统可能在使用某个类时加载该类,也可能采用预加载机制加载某个类。
2 当调用Java命令运行Java程序时,命令会启动一个Java虚拟机进程
3 当系统主动使用某个类时,如果类还没有被加载到内存,系统会通过加载,连接,初始化来对类进行初始化,类加载是指将类的class文件读入内存,并创建一个class对象。
4 类的连接:生成一个class对象后,进入连接阶段,负责把二进制数据合并到jre中
1 验证 :检验类是否有正确的内部结构 2 准备:为类的静态field分配内存,设置默认初值 3 解析:将二进制数据中的符号引用变成直接引用
5 类的初始化 : 主要对静态field进行初始化 1 声明静态field时指定初值 ,2 使用静态初始化块
类初始化时机 1 创建类实例 new 反射创建 反序列化创建 2 调用类的静态方法 3 访问类或接口静态field 或为静态field复制 4 反射创建类的class对象 Class.forName(), 5 使用java命令运行某个主类
final型的静态field,如果field值在编译时确定,相当于宏变量,编译器会在编译时把field出现的地方替换成他的值,不会导致类初始化。
classLoader类loadclass方法加载某个类时,只加载类,不会初始化类
public class JDBCTest extends Thread{ public static void main(String[] args) throws ClassNotFoundException { // System.out.println(A.a); // System.out.println(A.b); ClassLoader c = ClassLoader.getSystemClassLoader(); c.loadClass("com.whe.db.A"); } } class A { public final static int a = 0; public final static int b = new Random().nextInt(10); static{ System.out.println("chu shi hua"); } }
6 Java中的类使用包名类名做唯一标识 jvm使用包名,类名,加载器名做唯一标识。根类:加载核心类库 String system 扩展 : jre/lib/ext extension 3 系统: -classpath java.class.path 属性
7 类加载机制 1 全盘负责:当一个类加载器负责加载某个class时,该class所依赖和引用的其他class也将由该类加载器载入 2 父类委托 先让父类加载器试图加载该class , 只有在父类加载器无法加载时,才尝试从自己类路径加载该类。3 缓存 机制 , 保证所有加载过的class都会被缓存,缓存不存在时才读取类的二进制数据,并转换成class对象,放入缓存区
file:/D:/andro/Test/bin/ D:\program\1.7\jre\lib\ext;C:\Windows\Sun\Java\lib\ext public class JDBCTest extends Thread{ public static void main(String[] args) throws ClassNotFoundException, IOException { ClassLoader c = ClassLoader.getSystemClassLoader(); Enumeration<URL> e = c.getResources(""); while (e.hasMoreElements()) { System.out.println(e.nextElement()); } ClassLoader cp = c.getParent(); System.out.println(System.getProperty("java.ext.dirs")); } }
8 获取class对象
Class a = Class.forName("com.whe.db.A");
Class b = A.class; 比较好,可以在编译时期获得,不会抛出异常
A c = new A();
Class d = c.getClass();
9 创建对象
public class JDBCTest extends Thread{ public static void main(String[] args) throws Exception { Class a = Class.forName("com.whe.db.A"); Constructor c = a.getConstructor(String.class); c.newInstance("ds"); a.newInstance(); } } class A { public A() { System.out.println("con"); } public A(String name) { System.out.println(name); } }
10 调用方法
public class JDBCTest extends Thread{ public static void main(String[] args) throws Exception { Class a = Class.forName("com.whe.db.A"); A b = (A) a.newInstance(); Method m =a.getDeclaredMethod("info", String.class); m.setAccessible(true); m.invoke(b, "i am jory"); } } class A { private void info(String name) { System.out.println(name); } }
11 动态代理
public class JDBCTest implements InvocationHandler{ public static void main(String[] args) throws Exception { JDBCTest ih = new JDBCTest(); Person p = (Person)Proxy.newProxyInstance(JDBCTest.class.getClassLoader(), Person.class, ih); p.walk(); p.sayHello("dds"); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println(" ---- " + method + "----- "); if (args == null) { System.out.println("no args"); } else { for (Object str : args) { System.out.println(str); } } return null; } } interface Person { void walk(); void sayHello(String name); }
public static <T> T newI(Class<T> c) { try { return c.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }