Java基礎-類加載機制與自定義類Java類加載器(ClassLoader)


         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 }
Person.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 
 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 */
TestJVM.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 
 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  */
TestJVM.java 文件內容(反射觸發靜態代碼塊的執行)

 

二.編寫自定義類加載器

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 }
Yinzhengjie.java 文件內容

  使用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>.得到自定義加載器

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM