更新時間:2020-03-12 09:19:07 來源:動力節點 瀏覽2374次
一、類加載
定義
當程序要使用某個類時,如果該類還未被加載到內存中,則系統會通過加載,連接,初始化三步來實現對這個類進行初始化
加載
就是指將.class文件讀入內存,并為之創建一個Class對象。任何類被使用時系統都會建立一個Class對象。
連接
驗證是否有正確的內部結構,并和其他類協調一致
準備負責為類的靜態成員分配內存,并設置默認初始化值
解析將類的二進制數據中的符號引用替換為直接引用
初始化就是我們以前講過的初始化步驟
2.加載的時機
創建類的實例
訪問類的靜態變量,或者為靜態變量賦值
調用類的靜態方法
使用反射方式來強制創建某個類或接口對應的java.lang.Class對象
加載某個類的子類
直接使用java.exe命令來運行某個主類
真正在使用這個類型的時候
二、類加載器的概述和分類
定義
負責將.class文件加載到內存中,并為之生成對應的Class對象。雖然我們不需要關心類加載機制,但是了解這個機制我們就能更好的理解程序的運行
2.類加載器的分類
BootstrapClassLoader根類加載器
ExtensionClassLoader擴展類加載器
SysetmClassLoader系統類加載器
AppClassLoader應用類加載器
3.類加載器的作用
BootstrapClassLoader根類加載器
也被稱為引導類加載器,負責Java核心類的加載
比如System,String等。在JDK中JRE的lib目錄下rt.jar文件中
ExtensionClassLoader擴展類加載器
負責JRE的擴展目錄中jar包的加載。
在JDK中JRE的lib目錄下ext目錄
SysetmClassLoader系統類加載器
負責在JVM啟動時加載來自java命令的class文件,以及classpath環境變量所指定的jar包和類路徑
AppClassLoader加載其他類
負載一些非核心類和程序猿自己寫的類
4.演示
publicstaticvoidmain(String[]args){ //獲取TestDemo類的類加載器 System.out.println(TestDemo.class.getClassLoader()); }
三、自定義類加載器
雙親委派模型
當前類加載器從自己已經加載的類中查詢是否此類已經加載,如果已經加載則直接返回原來已經加載的類。
如果沒有找到,就去委托父類加載器去加載(如代碼c=parent.loadClass(name,false)所示)。父類加載器也會采用同樣的策略,查看自己已經加載過的類中是否包含這個類,有就返回,沒有就委托父類的父類去加載,一直到根類加載器。因為如果父加載器為空了,就代表使用根類類加載器作為父加載器去加載
如果根類類加載器加載失敗(例如在$JAVA_HOME/jre/lib里未查找到該class),會使用拓展類加載器來嘗試加載,繼續失敗則會使用AppClassLoader來加載,繼續失敗則會拋出一個異常ClassNotFoundException,然后再調用當前加載器的findClass()方法進行加載
2.好處
主要是為了安全性,避免用戶自己編寫的類動態替換Java的一些核心類,比如String。
同時也避免了類的重復加載,因為JVM中區分不同類,不僅僅是根據類名,相同的class文件被不同的ClassLoader加載就是不同的兩個類
案例演示
publicclassMyClassLoaderextendsClassLoader{ privateStringpath; publicMyClassLoader(Stringpath){ super(); this.path=path; } @Override protectedClass<?>findClass(Stringname)throwsClassNotFoundException{ //讀取本地文件 byte[]bs=getBytes(path); //將字節數組裝載成Class對象 Class<?>clazz=this.defineClass(name,bs,0,bs.length); returnclazz; } privatebyte[]getBytes(Stringpath){ try( FileInputStreamfis=newFileInputStream(path); ByteArrayOutputStreambos=newByteArrayOutputStream(); ){ byte[]bs=newbyte[1024]; intlen; while((len=fis.read(bs))!=-1){ bos.write(bs,0,len); } returnbos.toByteArray(); }catch(Exceptione){ } returnnull; } } publicstaticvoidmain(String[]args)throwsException{ MyClassLoaderclassLoader=newMyClassLoader("D:\\Student.class"); Class<?>clazz=classLoader.findClass("com.qianfeng.Student"); //Class<?>class1=Class.forName("com.qianfeng.Student",true,classLoader); Objectobj=clazz.newInstance(); System.out.println(obj.getClass().getClassLoader()); }
四、反射
定義
JAVA反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法
對于任意一個對象,都能夠調用它的任意一個方法和屬性
這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制
要想解剖一個類,必須先要獲取到該類的字節碼文件對象
而解剖使用的就是Class類中的方法,所以先要獲取到每一個字節碼文件對應的Class類型的對象
說白了就是獲取一個類的骨架
2.獲取字節碼的三種方式
對象.getClass()
類名.class
Class類中靜態方法forName("類名")
3.演示
publicstaticvoidmain(String[]args)throwsException{ Studentstudent=newStudent(); Class<?>clazz1=student.getClass(); Class<?>clazz2=Student.class; Class<?>clazz3=Class.forName("com.qianfeng.Student"); }
五、反射獲取構造函數
定義
Class類的newInstance()方法是使用該類無參的構造函數創建對象
如果一個類沒有無參的構造函數,就不能這樣創建了,可以調用Class類的getConstructor(String.class,int.class)方法獲取一個指定的構造函數然后再調用Constructor類的newInstance("張三",20)方法創建對象
2.演示
publicstaticvoidmain(String[]args)throwsException{ Class<?>clazz=Class.forName("com.qianfeng.Student"); Studentobject=(Student)clazz.newInstance(); object.method(); }
以上就是動力節點Java培訓機構小編介紹的“Javaweb學習視頻:反射動態代理”的內容,希望對大家有幫助,如有疑問,請在線咨詢,有專業老師隨時為你服務。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習