Java基礎-類加載機制與自定義類Java類加載器(ClassLoader)
作者:尹正傑
版權聲明:原創作品,謝絕轉載!否則將追究法律責任。
關於類加載器的概念和分類我就不再廢話了,因為我在之前的筆記已經提到過了,詳細能看到這篇文章的這些概念應該都爛熟於胸啦!如果你是一名小白的話可以參考我以前的筆記:https://www.cnblogs.com/yinzhengjie/p/9272289.html。本篇博客的重點側重三點,第一,測試靜態代碼塊;第二,編寫自定義類加載器;第三,驗證四級類加載機制。
一.測試靜態代碼塊
1>.靜態代碼塊的作用
答:靜態代碼塊的作用說白了跟構造方法的功能類似,他們都可以給類的成員變量進行賦值操作,我們可以簡單的理解為靜態代碼塊是為了給類初始化,構造方法是為了給對象初始化。
2>.靜態代碼塊在加載類的必須會被執行嗎?
答:答案是否定的,我們在加載類的時候,可以不指定加載靜態代碼塊。但是,只要你新建一個實例或者是通過反射的方式創建一個實例,依然還是會觸發靜態代碼塊的執行。我們在加載類是指定不加載靜態代碼塊說白了只是延時它的加載,因為在實例化的過程中依然會加載!
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.jvm; 7 8 public class Person { 9 public String name; 10 private int age; 11 public String sex; 12 13 static { 14 System.out.println("I'm yinzhengjie !!!"); 15 } 16 17 public Person(String name, int age, String sex) { 18 this.name = name; 19 this.age = age; 20 this.sex = sex; 21 } 22 23 public Person() { } 24 25 public String getName() { 26 return name; 27 } 28 29 public void setName(String name) { 30 this.name = name; 31 } 32 33 public int getAge() { 34 return age; 35 } 36 37 public void setAge(int age) { 38 this.age = age; 39 } 40 41 public String getSex() { 42 return sex; 43 } 44 45 public void setSex(String sex) { 46 this.sex = sex; 47 } 48 49 @Override 50 public String toString() { 51 return "Person{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}'; 52 } 53 }
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.jvm; 8 9 import org.junit.Test; 10 11 import java.lang.reflect.Field; 12 13 public class TestJVM { 14 15 @Test 16 public void testClassLoader() throws Exception { 17 //通過ClassLoader.getSystemClassLoader()獲取系統加載類,將類的初始化操作設置為false. 18 Class c1 = Class.forName("cn.org.yinzhengjie.jvm.Person",false,ClassLoader.getSystemClassLoader()); 19 Field name = c1.getDeclaredField("name"); 20 System.out.println(name); 21 } 22 } 23 24 /* 25 以上代碼輸出結果如下: 26 public java.lang.String cn.org.yinzhengjie.jvm.Person.name 27 */
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.jvm; 8 9 import org.junit.Test; 10 11 import java.lang.reflect.Field; 12 13 public class TestJVM { 14 15 @Test 16 public void testClassLoader() throws Exception { 17 //通過ClassLoader.getSystemClassLoader()獲取系統加載類,將類的初始化操作設置為false. 18 Class c1 = Class.forName("cn.org.yinzhengjie.jvm.Person",false,ClassLoader.getSystemClassLoader()); 19 Field field = c1.getDeclaredField("name"); 20 System.out.println(field); 21 //雖然上面的代碼再加載類的過程中設置禁用靜態代碼塊的加載,通過反射獲取到的時候依然會觸發靜態代碼塊的執行! 22 Object obj = c1.newInstance(); 23 field.set(obj,"尹正傑"); 24 System.out.println(obj); 25 } 26 } 27 28 /* 29 以上代碼輸出結果如下: 30 public java.lang.String cn.org.yinzhengjie.jvm.Person.name 31 I'm yinzhengjie !!! 32 Person{name='尹正傑', age=0, sex='null'} 33 */
二.編寫自定義類加載器
1>.編寫自定義類加載器
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.jvm; 7 8 import java.io.ByteArrayOutputStream; 9 import java.io.FileInputStream; 10 11 /** 12 * 自定義ClassLoader 13 */ 14 public class MyClassLoader extends ClassLoader { 15 protected Class<?> findClass(String name) { 16 try { 17 String path = "D:\\BigData\\JavaSE\\yinzhengjieData\\" + name + ".class" ; 18 FileInputStream in = new FileInputStream(path) ; 19 ByteArrayOutputStream baos = new ByteArrayOutputStream() ; 20 byte[] buf = new byte[1024] ; 21 int len = -1 ; 22 while((len = in.read(buf)) != -1){ 23 baos.write(buf , 0 , len); 24 } 25 in.close(); 26 byte[] classBytes = baos.toByteArray(); 27 return defineClass(classBytes , 0 , classBytes.length) ; 28 } catch (Exception e) { 29 e.printStackTrace(); 30 } 31 return null ; 32 } 33 }
2>.調用自定義類加載器
在“D:\BigData\JavaSE\yinzhengjieData”目錄下編寫測試代碼如下:
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 public class Yinzhengjie { 8 private String name; 9 private int age; 10 static { 11 System.out.println("I'm yinzhengjie !"); 12 } 13 14 public Yinzhengjie(String name, int age) { 15 this.name = name; 16 this.age = age; 17 } 18 19 public Yinzhengjie() { 20 } 21 22 public String getName() { 23 return name; 24 } 25 26 public void setName(String name) { 27 this.name = name; 28 } 29 30 public int getAge() { 31 return age; 32 } 33 34 public void setAge(int age) { 35 this.age = age; 36 } 37 38 @Override 39 public String toString() { 40 return "Yinzhengjie{" + "Name = " + name + ", Age = " + age + '}'; 41 } 42 }
使用javac命令編譯Java代碼。

調用咱們自定義的類加載器,測試代碼如下:
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.jvm; 7 8 import java.lang.reflect.Constructor; 9 10 public class MyClassLoaderApp { 11 public static void main(String[] args) { 12 //創建自定義類加載器實例 13 ClassLoader cl = new MyClassLoader() ; 14 cl.getParent(); 15 try { 16 Class clz = cl.loadClass("Yinzhengjie") ; 17 Constructor constructor = clz.getConstructor(String.class, int.class); 18 Object obj = constructor.newInstance("尹正傑", 18); 19 System.out.println(obj); 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } 23 } 24 } 25 26 /* 27 以上代碼執行結果如下: 28 I'm yinzhengjie ! 29 Yinzhengjie{Name = 尹正傑, Age = 18} 30 */
三.驗證四級類加載機制
1>.根類加載器是得不到的

2>.得到擴展類加載器

3>.得到系統類加載器
4>.得到自定義加載器
