天天看點

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

文章目錄

  • 概述:
    • (1)基本知識:
    • (2)類的加載與ClassLoader的了解:
    • (3)使用ClassLoader加載配置檔案:
  • 一、了解class類并執行個體化class類對象:
  • 二、通過反射調用類的完整結構:
    • 1.獲得全部接口、所繼承的父類:
    • 2.全部的構造器:
    • 3.全部的方法:
    • 4.全部的Field:
    • 5.類所在的包:
    • 6.類聲明的注解:
  • 三、通過反射建立運作時類的對象:
    • 1.建立對象:
    • 2.通過反射強制調用私有的構造方法:
  • 四、通過反射調用類中的指定方法、指定屬性:
    • 1.調用指定方法:
    • 2.調用指定屬性:
    • 3.調用指定的構造器:
  • 五、一些疑問:
  • 六、Java動态代理:

概述:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

(1)基本知識:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:
2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

反射機制:就是通過一個抽象的類名能夠在自己記憶(加載類的記憶體)中,找到這個類的具體資訊。

前提:jvm已經加載過這個類,相當于有了對這個類的記憶。

1.類的加載過程:

程式經過javac.exe指令以後,會生成一個或多個位元組碼檔案(.class結尾)(編譯過程);接着使用java.exe指令對某個位元組碼檔案進行解釋運作,相當于将某個位元組碼檔案加載到記憶體中了(類的加載)。加載到記憶體中的類,就稱為運作時類,此時運作時類就作為 Class的一個執行個體。

2.換言之,Class的執行個體就對應這一個運作時類。

3.加載到記憶體中的運作時類,會緩存一段時間。在此時間内,我們可以通過不同的方式來擷取此運作時類。

(2)類的加載與ClassLoader的了解:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:
2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

(3)使用ClassLoader加載配置檔案:

方式一:

Properties properties = new Properties();
		//此時的檔案預設在目前的工程下(eclipse中),(IDEA中預設在目前module下)
		//方式一:
		FileInputStream fis = new FileInputStream("jdbc.properties");
		properties.load(fis);
		
		String user = properties.getProperty("User");
		String password = properties.getProperty("password");
		
		System.out.println("User=" + user);
		System.out.println("password=" + password);
           

方式二:使用ClassLoader;配置檔案預設識别為:目前module的src下(IDEA中)

Properties properties = new Properties();
		ClassLoader classLoader = Reflection.class.getClassLoader();
		InputStream resourceAsStream = classLoader.getResourceAsStream("jdbc.properties");
		
		properties.load(resourceAsStream);
		
		String user = properties.getProperty("User");
		String password = properties.getProperty("password");
		
		System.out.println("User=" + user);
		System.out.println("password=" + password);
           

一、了解class類并執行個體化class類對象:

Class類:用來描述類的類。

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:
2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:
2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

隻要數組的元素類型與次元一樣,就是同一個Class。

int[] a = new int [10];
		int[] b = new int [100];
		Class ac = a.getClass();
		Class bc = b.getClass();
		System.out.println(ac==bc);//true
           
2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:
2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:
2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

二、通過反射調用類的完整結構:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

1.獲得全部接口、所繼承的父類:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

3.擷取運作時類的泛型

4.擷取運作時類的帶泛型的父類的泛型

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

2.全部的構造器:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

getConstructor():擷取目前運作時類中聲明為public權限的構造器。

getDeclaredConstructor():擷取目前運作時類中聲明的所有構造器。

getModifiers():傳回數字1,代表public;傳回數字2,代表private;傳回數字0,代表default。也可以使用:Modifer下的toString方法,顯示相關的權限名稱。

int modifier = f.getModifiers();
System.out.println(Modifier.toString(modifier));
           

3.全部的方法:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

抛出的異常:public Class[] getExceptionTypes();

getMethods():擷取目前運作時類及其所有父類中聲明為public權限的方法。

getDeclaredMethod():擷取目前運作時類中聲明的所有方法。(不包含父類中)

getParameterTypes():擷取方法的參數類型,傳回一個數組,方法有幾個參數,數組就有幾個元素。

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

4.全部的Field:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

getFields():擷取類的公有的屬性,包含父類的公有屬性;

getDeclaredFields():擷取本類的(不包括父類的屬性)所有的屬性,包括私有。

5.類所在的包:

Package getPackage()

6.類聲明的注解:

Annotation[] getAnnotations();

三、通過反射建立運作時類的對象:

1.建立對象:

1.利用newInstance()方法;調用此方法建立運作時類的對象,内部調用了運作時類的空參構造器。

要想此方法正常的建立運作時類的對象,要求:

(1)運作時類必須提供空參構造器;

(2)空參構造器的通路權限的夠。一般為public。

補充:

在JavaBean中要求提供一個public的空參構造器,其原因:

(1)便于通過反射,建立運作時類的對象;

(2)便于子類繼承此運作時類時,預設調用super(),保證父類有此構造器。

2.getConstructor();指定構造器,然後在用newInstance()執行個體化對象。

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

3.根據類的路徑建立指定類的執行個體(一個方法):

public static Object createInstance(String classPath) throws Exception {
		Class clazz = Class.forName(classPath);
		return clazz.newInstance();
	}
           

2.通過反射強制調用私有的構造方法:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

四、通過反射調用類中的指定方法、指定屬性:

1.調用指定方法:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

(1)getMethod(String name, Class…parameterTypes):第一個參數為調用方法的名稱(字元串類型),第二個為方法中的參數(形參清單)。

(2)method.invoke(Object obj, Object[] args):參數1是需要執行個體化的對象(方法的調用者),後面的參數是調用目前方法實際參數。invoke()方法的傳回值即為對應類中調用的方法的傳回值。如果該方法沒有傳回值,則invoke()傳回null。

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

(3)調用一個私有方法:

使用getDeclaredMethod()方法。參數形式、用法與getMethod()相同。

注意:getDeclaredMethod()擷取到方法之後,需要用setAccessible(true) 來解除私有封裝,進行強制調用私有方法。

(4)調用有傳回值的方法:

注意傳回值得接收。

2.調用指定屬性:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:
2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:
2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理:

3.調用指定的構造器:

(1)getDeclaredConstructor(指定參數清單):擷取指定的構造器。參數:指明構造器的參數清單(變量類型)

(2)保證構造器的通路權限:constructor.setAccessible(true);

(3)調用此構造器建立運作時類的對象:constructor.newInstance(“實際參數”);

使用确定的構造器來建立對象有限制(不通用),一般使用較少;通常還是使用newInstance()方法來建立對象(動态性高)。

五、一些疑問:

(1)通過直接new的方式或反射的方式都可以調用公共的結構,開發中用那個?

建議直接用new的方式。若在編譯的時候不能确定具體new那個對象,此時會用反射的方式建立對象(反射動态性的展現)。

(2)反射機制與面向對象中的封裝性是不是沖突的?如何看待兩個技術?

不沖突。

六、Java動态代理:

2020.11.29——反射概述:一、了解class類并執行個體化class類對象:二、通過反射調用類的完整結構:三、通過反射建立運作時類的對象:四、通過反射調用類中的指定方法、指定屬性:五、一些疑問:六、Java動态代理: