類的加載、連接與初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class Test { public static void main(String[] args) { Count count = Count.getInstance(); System.out.println( "count1 = " + count.count1); System.out.println( "count2 = " + count.count2); } } class Count { // 這個運行結果是 count1 = 1 count2 = 0 ; 因爲按順序執行1. Count(); 2. count1; 3. count2; private static Count count = new Count(); public static int count1; public static int count2 = 0 ; // 所以這個運行結果是 count1 = 1 count2 = 1 ; // private static Count count = new Count(); private Count() { count1++; count2++; } public static Count getInstance() { return count; } } |
1. 類的加載
2. 連接
2.1 類的驗證
2.2 類的準備
1 2 3 4 5 6 7 8 9 | public class Sample { private static int a = 1 ; private static long b; static { b = 2 ; } // ... } |
2.3 類的解析
1 2 3 | public void gotoWord(){ car.run(); //這段代碼在Worker類的二進制數據中表示爲符號引用 } |
3. 類的初始化
1 2 3 4 5 6 7 8 9 10 | public class Sample { private static int a = 1 ; private static long b; private static long c; static { b = 2 ; } // ... } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Sample { private static int a = 1 ; static { a = 2 ; } static { a = 4 ; } public static void main(String[] args) { System.out.println(a); // 輸出4 } } |
3. 1 類的初始化時機
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class Test { public static void main(String[] args) { // x是一個編譯時的常量,編譯的時候就知道值是多少,不需要對類進行初始化
System.out.println(FinalTest.x); // x非編譯時的常量,x在編譯時不知道是多少, // 運行才知道的就需要對類進行初始化,對類進行初始化static代碼快就會執行 System.out.println(FinalTest2.x); } } class FinalTest { public static final int x = 6 / 3 ; static { System.out.println( "FinalTest staic block!" ); } } class FinalTest2 { public static final int x = new Random().nextInt( 100 ); static { System.out.println( "FinalTest2 staic block!" ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class Test { static { System.out.println( "Test static block!" ); } public static void main(String[] args) { System.out.println(Child.b); } } class Parent { static int a = 3 ; static { System.out.println( "Parent static block!" ); } } class Child extends Parent { static int b = 4 ; static { System.out.println( "Child static block!" ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class Test { public static void main(String[] args) { System.out.println(Child.a); Child.doSomething(); } } class Parent { static int a = 3 ; static { System.out.println( "Parent static block!" ); } static void doSomething() { System.out.println( "do something!" ); } } class Child extends Parent { static { System.out.println( "Child static block!" ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Test { public static void main(String[] args) throws ClassNotFoundException { // 獲取系統類加載器 ClassLoader loader = ClassLoader.getSystemClassLoader(); // 這行代碼沒有導致任何輸出 不會導致類的初始化 Class<?> clazz = loader.loadClass( "CL" ); System.out.println( "------" ); clazz = Class.forName( "CL" ); } } class CL { static { System.out.println( "Class CL" ); } } |
類加載器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Test { public static void main(String[] args) throws ClassNotFoundException { // String 是由根類加載器加載的,下面打印結果爲null Class<?> clazz = Class.forName( "java.lang.String" ); System.out.println(clazz.getClassLoader()); // 應用加載器加載的 Class<?> clazz2 = Class.forName( "C" ); System.out.println(clazz2.getClassLoader()); } } class C { } |
類加載的父委託機制
1 2 3 4 | ClassLoader loader1 = new MyClassLoader(); // 參數loader1將作爲loader2的父加載器 ClassLoader loader2 = new MyClassLoader(loader1); |
命名空間
運行時包(package)
創建用戶自定義的類加載器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | public class MyClassLoader extends ClassLoader { // 類加載器名字 private String name; // 加載類的路徑 private String path = "d:\\" ; // class文件的擴展名 private final String fileType = ".class" ; public MyClassLoader(String name) { super (); // 讓系統類加載器成爲該類加載器的父加載器 this .name = name; } public MyClassLoader(ClassLoader parent, String name) { super (parent); // 顯示指定該類加載器的父加載器 this .name = name; } public String toString() { return this .name; } public String getPath() { return path; } public void setPath(String path) { this .path = path; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte [] data = this .loadClassData(name); return this .defineClass(name, data, 0 , data.length); } private byte [] loadClassData(String name) { InputStream is = null ; byte [] data = null ; ByteArrayOutputStream baos = null ; try { this .name = this .name.replace( "." , "\\" ); is = new FileInputStream( new File(path + name + fileType)); baos = new ByteArrayOutputStream(); int ch = 0 ; while (- 1 != (ch = is.read())) { baos.write(ch); } data = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { try { baos.close(); is.close(); } catch (IOException e) { e.printStackTrace(); } } return data; } public static void main(String[] args) throws Exception { // 父加載器爲系統類加載器 MyClassLoader loader1 = new MyClassLoader( "loader1" ); loader1.setPath( "D:\\test\\serverlib\\" ); // 指定loader2的父加載器爲loader1 MyClassLoader loader2 = new MyClassLoader(loader1, "loader2" ); loader2.setPath( "D:\\test\\clientlib\\" ); // 指定loader3的父加載器爲根加載器 MyClassLoader loader3 = new MyClassLoader( null , "loader3" ); loader3.setPath( "D:\\test\\otherlib\\" ); test(loader2); test(loader3); } public static void test(ClassLoader loader) throws Exception { Class clazz = loader.loadClass( "Sample" ); Object object = clazz.newInstance(); } } |
1 2 3 4 5 6 | public class Dog { public Dog() { System.out.println( "Dog is load by : " + this .getClass().getClassLoader()); } } |
1 2 3 4 5 6 7 8 9 10 11 12 | public class Sample { public int v1 = 1 ; public Sample() { System.out.println( "Sample is load by : " + this .getClass().getClassLoader()); // 主動使用Dog new Dog(); } } |
1 2 3 4 5 | D:\myapp\syslib>java MyClassLoader Sample is load by : loader1 Dog is load by : loader1 Sample is load by : loader3 Dog is load by : loader3 |
1 2 3 4 5 | D:\myapp\syslib>java MyClassLoader Sample is load by : sun.misc.Launcher$AppClassLoader@659e0bfd Dog is load by : sun.misc.Launcher$AppClassLoader@659e0bfd Sample is load by : loader3 Dog is load by : loader3 |
1 2 3 4 5 | D:\myapp\syslib>java - cp .;d:\myapp\serverlib MyClassLoader Sample is load by : sun.misc.Launcher$AppClassLoader@659e0bfd Dog is load by : sun.misc.Launcher$AppClassLoader@659e0bfd Sample is load by : loader3 Dog is load by : loader3 |
1 2 3 4 5 | D:\myapp\syslib>java MyClassLoader Sample is load by : loader1 Dog is load by : sun.misc.Launcher$AppClassLoader@659e0bfd Sample is load by : loader3 Dog is load by : loader3 |
1 2 3 4 5 6 7 8 9 10 11 | public static void main(String[] args) throws Exception { // 父加載器爲系統類加載器 MyClassLoader loader1 = new MyClassLoader( "loader1" ); loader1.setPath( "D:\\myapp\\serverlib\\" ); Class clazz = loader1.loadClass( "Sample" ); Object object = clazz.newInstance(); // 創建對象 Sample sample = (Sample)object; System.out.println(sample.v1); } |
1 2 3 4 5 6 7 8 9 10 11 | D:\myapp\syslib>java MyClassLoader Sample is load by : loader1 Dog is load by : loader1 Exception in thread "main" java.lang.NoClassDefFoundError: Sample at MyClassLoader.main(MyClassLoader.java:110) Caused by: java.lang.ClassNotFoundException: Sample at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) ... 1 more |
1 2 3 4 5 6 7 8 9 10 11 12 | public static void main(String[] args) throws Exception { // 父加載器爲系統類加載器 MyClassLoader loader1 = new MyClassLoader( "loader1" ); loader1.setPath( "D:\\myapp\\serverlib\\" ); Class clazz = loader1.loadClass( "Sample" ); Object object = clazz.newInstance(); // 創建對象 Field field = clazz.getField( "v1" ); int v1 = field.getInt(object); System.out.println( "v1:" + v1); } |
1 2 3 4 | D:\myapp\syslib>java MyClassLoader Sample is load by : loader1 Dog is load by : loader1 v1:1 |
類的卸載
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public static void main(String[] args) throws Exception { // 父加載器爲系統類加載器 MyClassLoader loader1 = new MyClassLoader( "loader1" ); //1 loader1.setPath( "D:\\myapp\\serverlib\\" ); //2 Class objClass = loader1.loadClass( "Sample" ); //3 System.out.println( "objClass's hashCode is " + objClass.hashCode()); //4 Object obj = objClass.newInstance(); // 創建對象 //5 loader1 = null ; //6 objClass = null ; //7 obj = null ; //8 loader1 = new MyClassLoader( "loader1" ); //9 objClass = loader1.loadClass( "Sample" ); //10 System.out.println( "objClass's hashCode is " + objClass.hashCode()); //11 } |
1 2 3 4 5 | D:\myapp\syslib>java MyClassLoader objClass's hashCode is 1311053135 Sample is load by : loader1 Dog is load by : loader1 objClass's hashCode is 865113938 |