類的加載概述和加載時機
A:類的加載概述
當程式要使用某個類時,如果該類還未被加載到記憶體中,則系統會通過加載,連接配接,初始化三步來實作對這個類進行初始化。
加載
就是指将class檔案讀入記憶體,并為之建立一個Class對象。
任何類被使用時系統都會建立一個Class對象。
連接配接
驗證 : 是否有正确的内部結構,并和其他類協調一緻
準備 : 負責為類的靜态成員配置設定記憶體,并設定預設初始化值
解析: 把類中的符号引用轉換為直接引用
初始化
就是我們以前講過的初始化步驟
B:類的加載時機
建立類的執行個體
通路類的靜态變量,或者為靜态變量指派
調用類的靜态方法
使用反射方式來強制建立某個類或接口對應的java.lang.Class對象
初始化某個類的子類
直接使用java.exe指令來運作某個主類
類加載器的概述和分類
A:類加載器的概述
負責将.class檔案加載到内在中,并為之生成對應的Class對象。
B:類加載器的分類
Bootstrap ClassLoader 根類加載器
Extension ClassLoader 擴充類加載器
Sysetm ClassLoader 系統類加載器
C:類加載器的作用
Bootstrap ClassLoader 根類加載器
也被稱為引導類加載器,負責Java核心類的加載
比如System,String等。在JDK中JRE的lib目錄下rt.jar檔案中
Extension ClassLoader 擴充類加載器
負責JRE的擴充目錄中jar包的加載。
在JDK中JRE的lib目錄下ext目錄
Sysetm ClassLoader 系統類加載器
負責在JVM啟動時加載來自java指令的class檔案,以及classpath環境變量所指定的jar包和類路徑
反射概述以及擷取class檔案對象的三種方式
A:反射概述
JAVA反射機制是在運作狀态中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動态擷取類的資訊以及動态調用對象的方法的功能稱為java語言的反射機制。要想解剖一個類,必須先要擷取到該類的位元組碼檔案對象。而解剖使用的就是Class類中的方法,是以先要擷取到每一個位元組碼檔案對應的Class類型的對象
B:擷取class檔案對象的三種方式
a:Object類的getClass()方法
b:靜态屬性class
c:Class類中靜态方法forName()
C:案例示範: 擷取class檔案對象的三種方式
反射: 就是在運作狀态中的一種動态調用方法或者屬性的一種機制.
- 就是擷取位元組碼檔案對象,然後剖析改類中存在哪些構造方法,哪些成員變量,哪些成員方法
- 類的成員
- 成員變量 Field
- 構造方法 Constructor
-
成員方法 Method
- 如何擷取一個類對應的位元組碼檔案對象:
- a: 第一種通過Object類中的getClass方法
- b: 通過靜态屬性(class屬性)
- c: 通過Class類中的一個靜态方法:
- public static Class forName(String className):
- className: 這個表示的是一個類對應的全類名(就是需要加上包名)
-
類加載器與反射,動态代理 -
類加載器與反射,動态代理
通過反射擷取無參構造方法并使用
A:擷取所有構造方法
public Constructor<?>[] getConstructors() 擷取所有的構造方法不包含私有的
public Constructor<?>[] getDeclaredConstructors() 擷取所有的構造方法 包括私有的
B:擷取單個構造方法
public Constructor getConstructor(Class<?>… parameterTypes) 擷取單個的構造方法 不包含私有的
public Constructor getDeclaredConstructor(Class<?>… parameterTypes) 擷取單個的構造方法包含私有的
C:案例示範: 通過反射擷取無參構造方法并使用
通過反射擷取帶參構造方法并使用
A:案例示範: 通過反射擷取帶參構造方法并使用
通過反射擷取私有構造方法并使用
A:案例示範: 通過反射擷取私有構造方法并使用
// 擷取位元組碼檔案對象
Class clazz = Class.forName(“com.click369.Student”) ;
Constructor con = clazz.getDeclaredConstructor(String.class , int.class) ;
// 值為 true 則訓示反射的對象在使用時應該取消 Java 語言通路檢查。
con.setAccessible(true) ; 取消文法檢查不然會報錯 因為私有的外界不能直接通路
Object obj = con.newInstance(“張三” , 23) ;
System.out.println(obj);
通過反射擷取成員變量并使用
A:擷取所有成員變量
public Field[] getFields() 擷取所有的成員變量包含從父類繼承過來的
public Field[] getDeclaredFields() 擷取所有的成員變量 包含私有的 也包含從父類繼承過來的成員變量
B:擷取單個成員變量
public Field getField(String name)
public Field getDeclaredField(String name)
C:案例示範: 通過反射擷取成員變量并使用
通過反射擷取無參無傳回值成員方法并使用
A:擷取所有成員方法
public Method[] getMethods() //擷取所有的公共的成員方法不包含私有的 包含從父類繼承過來的過來的公共方法
public Method[] getDeclaredMethods()//擷取自己的所有成員方法 包含私有的
B:擷取單個成員方法
//參數1: 方法名稱 參數2:方法行參的class 對象
public Method getMethod(String name,Class<?>… parameterTypes) //擷取單個的方法 不包含私有的
public Method getDeclaredMethod(String name,Class<?>… parameterTypes) 擷取單個方法包括私有的
C:案例示範: 通過反射擷取無參無傳回值成員方法并使用
通過反射運作配置檔案内容
A:案例示範: 通過反射運作配置檔案内容
過反射寫一個通用的設定某個對象的某個屬性為指定的值
A:案例示範
public void setProperty(Object obj, String propertyName, Object value){},
此方法可将obj對象中名為propertyName的屬性的值設定為value。
動态代理的概述和實作
A:動态代理概述
代理:本來應該自己做的事情,卻請了别人來做,被請的人就是代理對象。
舉例:春季回家買票讓人代買
動态代理:在程式運作過程中産生的這個對象
而程式運作過程中産生對象其實就是我們剛才反射講解的内容,是以,動态代理其實就是通過反射來生成一個代理
在Java中java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler接口,通過使用這個類和接口就可以生成動态代理對象。JDK提供的代理隻能針對接口做代理。我們有更強大的代理cglib,Proxy類中的方法建立動态代理類對象。
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
最終會調用InvocationHandler的方法
InvocationHandler Object invoke(Object proxy,Method method,Object[] args)
B:案例示範: 動态代理的實作
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
loader: 類加載器
interfaces: 接口對應的一個Class數組
InvocationHandler: 這個其實就是要代理對象所做的事情的一個類的封裝
**注意:JDK給我們提供的動态代理,隻能對接口進行代理.
動态代理:
* 特點:位元組碼随用随建立,随用随加載
* 作用:不修改源碼的基礎上對方法增強
* 分類:
* 基于接口的動态代理
* 基于子類的動态代理
* 基于接口的動态代理:
* 涉及的類:Proxy
* 提供者:JDK官方
* 如何建立代理對象:
* 使用Proxy類中的newProxyInstance方法
* 建立代理對象的要求:
* 被代理類最少實作一個接口,如果沒有則不能使用
* newProxyInstance方法的參數:
* ClassLoader:類加載器
* 它是用于加載代理對象位元組碼的。和被代理對象使用相同的類加載器。固定寫法。
* Class[]:位元組碼數組
* 它是用于讓代理對象和被代理對象有相同方法。固定寫法。
* InvocationHandler:用于提供增強的代碼
* 它是讓我們寫如何代理。我們一般都是些一個該接口的實作類,通常情況下都是匿名内部類,但不是必須的。
* 此接口的實作類都是誰用誰寫。
* new InvocationHandler() {
/
* 作用:執行被代理對象的任何接口方法都會經過該方法
* 方法參數的含義
* @param proxy 代理對象的引用
* @param method 目前執行的方法
* @param args 目前執行方法所需的參數
* @return 和被代理對象方法有相同的傳回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
}
}