java反射(2)
通過這種能力可以徹底的瞭解自身的情況為下一步的動作做準備。
Reflection。這個字的意思是“反射、映象、倒影”,用在Java身上指的是我們可以於執行時載入、探知、使用編譯期間完全未知的classes。換句話說,Java程式可以載入一個執行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其物件實體、或對其fields設值、或喚起其methods。這種“看透class”的能力(the ability of the program to examine itself)被稱為introspection(內省、內觀、反省)。Reflection和introspection是常被並提的兩個術語。
在JDK在主要實現反射機制類都位於java.lang.reflect包中:
1.Class類:代表一個類
2.Field類:代表類的成員變數(成員變數也稱為類的屬性)
3.Method類:代表類的方法。
4.Constructor類:代表類的構造方法。
5.Array類
後面四個看看API就明白了
這裡主要說下Class類
Class是Reflection故事起源。針對任何您想探勘的class,唯有先為它產生一個Class object。
Class物件怎樣產生的?
根據API解釋
Class
沒有公共構造方法。Class
物件是在載入類時由 Java 虛擬機器以及通過呼叫類載入器中的
defineClass
方法自動構造的。
當一個class被載入,或當載入器(class loader)的defineClass()被JVM呼叫,JVM 便自動產生一個Class object。注意Class並沒有public constructor。
怎麼得到Class物件?
在我上一篇部落格上反射(1)也有提到。
這裡再說一下:
一般有三種方式得到Class物件:
1、利用每個類都有的getClass()
方法(java.lang.Object),
如String str = "xx";
Class c1 = str.getClass();
c1.getName();得到java.lang.String
2、利用static method------Class.forName()(最常被使用)
如Class c2 = Class.forName ("java.lang.String");
c2.getName();得到java.lang.String
3、類名.class方法
Class c3 = String.class;
c3.getName();得到java.lang.String
1)對於一些基本型別資料還可以通過.TYPE的方式,且看下面程式碼
package com.testclass;
import java.lang.reflect.Method;
public class Reflection {
public static void main(String args[])
{
try {
/**
* 我們的程式中的每個類都有一個相應的Class物件.每當新的類被編譯
* 完成,就會產生一個Class物件儲存與相同的.class檔案內.執行期間
* 當你想要產生該class的物件是,JVM便會檢查該型別的Class物件是
* 否被載入.如果沒被載入,JVM會根據名稱找到.class檔案並載入它
*
* java中每個class都有一個相應的Class物件,當編寫好一個類,編譯完成後,
* 在生成的.class檔案中,就產生一個Class物件,用來表示
* 這個類的型別資訊。獲得Class例項的三種方式
*/
//1、使用Class的靜態方法forName(),用類的名字獲取一個Class例項
Class c = Class.forName("com.testclass.TestOne");
System.out.println(c.getName());//輸出com.md5.TestOne
TestOne test = (TestOne)c.newInstance();//產生這個class類物件的一個例項,呼叫該類的無參的構造方法,作用等同於new TestOne();
/**
* 有異常處理
* newInstance建立物件例項的時候會呼叫無參的建構函式,
* 所以必需確保類中有無引數的建構函式,否則將會丟擲java.lang.InstantiationException異常。
*/
System.out.println("=====================================================");
//2、利用物件呼叫getClass()方法獲取該物件的的Class例項,物件實現存在
TestOne test2 = new TestOne();
Class c2 = test2.getClass();
System.out.println(c2.getName());//輸出com.md5.TestOne
Method[] m = c2.getDeclaredMethods();//得到TestOne中的所有型別的自定義的方法,
// Method[] m = c2.getMethods();//得到TestOne中的public型別的方法,不僅僅是自定義的,還有繼承於Object類的
System.out.println("TestOne中的所有方法");
for(Method m2 : m)
{
System.out.println(m2);
}
System.out.println("======================================================");
//3-1、運用.class方式獲取Class例項(類)
Class c3 = TestOne.class;
System.out.println(c3.getName());//輸出com.md5.TestOne
//3-2 運用.class的方式獲取Class例項(基本型別)
Class c4 = int.class;
System.out.println("基本型別Class例項:"+c4.getName());//輸出int
//3-3運用.class的方式獲取Class例項(封裝型別型別)
Class c5 = Integer.TYPE;//獲取的是這個Integer型別
System.out.println(c5.getName());//輸出int
Class c6 = Integer.class;//獲取的是這個Integer的Class物件
System.out.println(c6.getName());//輸出java.lang.Integer
} catch (ClassNotFoundException e) {//如果包下不存在相應的com.md5.TestOne的.class檔案,會丟擲異常
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InstantiationException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//使用一般方法構造例項
TestOne two = new TestOne();//靜態塊只會被載入一次,第二次建立物件,不會再載入靜態塊,只執行構造方法
}
}
class TestOne{
static {
System.out.println("靜態塊執行");
}
public TestOne(){
System.out.println("構造方法執行");
}
void getTest()
{
}
public void getTest2()
{
}
}
2)對於method方法還可以輸出方法的引數等資訊、
package com.testclass;
import java.lang.reflect.Method;
public class Reflection2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Class c = Class.forName("com.testclass.Test2");
Method[] m = c.getDeclaredMethods();
for(Method method : m)
{
Class[] pre = method.getParameterTypes();
/**
* 按照宣告順序返回 Class 物件的陣列,這些物件描述了此 Method 物件所表示的方法的形參型別。
* 如果底層方法不帶引數,則返回長度為 0 的陣列
*/
for(Class cc : pre)
{
// System.out.println(cc);//輸出所有引數型別
System.out.println(cc.getName());//輸出所有引數型別,這樣輸出更好
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Class c = Integer.class;
// System.out.println(c);//輸出class java.lang.Integer
// Class c = int.class;
// System.out.println(c);//輸出int
}
}
class Test2
{
public void getTest(Integer a,int b)
{
}
}
3)利用反射可以驗證一個物件是否屬於這個類
package com.testclass;
public class Reflection3 {
public static void main(String[] args) {
try {
Class c = Class.forName("com.testclass.Test2");//!!!
String s = "";
System.out.println(c.isInstance(s));//輸出false
System.out.println(c.isInstance(new Test2()));//輸出true
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4)反射在框架中用的很多,工廠模式,當你不斷的new 就不斷的分配記憶體空間,當你new到一定程度沒有空間的時候,不就出問題了。一般都不考慮用new來構造例項,除非特殊情況。
new是不在記憶體中有了空間的分配,當知道型別的時候可以new,當不知道型別的時候,不能new
還要明白在java裡面任何class都要裝載在虛擬機器上才能執行。Class.forName就是裝載類用的(和new 不一樣,要分清楚)。
Class.forName("oracle.jdbc.driver.OracleDriver");只有載入了資料庫驅動(就是載入這個.class檔案)之後,才能用DriverManager。
DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl","xxx","xxx");
5)利用反射,動態載入類
要動態載入類,必須有個介面或者是抽象類(A),反射所載入的類是A的實現類或者是子類,否則動態載入的類毫無意義可言。
AA a = (AA)(Class.forName("xxx.xxx.xxx.AAImplClass").newInstance());//其中的forName中的類路徑可以動態的傳進來
7)陣列物件的反射(這個還在研究中)
int[] a = new int[2];
int[]b = new int[5];
System.out.println(a.getClass().getName());//輸出結果 [I
System.out.println(b.getClass().getName());////輸出結果 [I
6)此外,我們還可以在servlet中發現發射的影子
有時我們會奇怪,當我們把一個form表單提交給一個servlet處理時,我們並沒有建立這個servlet物件,但是怎麼呢呼叫其中的方法的呢?
當一個request請求傳遞給web伺服器後,web伺服器利用發射機制建立相應servlet物件,這個物件呼叫init方法將這個物件例項載入記憶體中(init方法只呼叫一次),然後就可以用這個例項呼叫servlet中的各種方法
相關文章
- 【Java 反射學習】Java 反射基礎Java反射
- [Java 反射學習] Java 反射基礎Java反射
- Java 反射Java反射
- Java——反射Java反射
- Java反射Java反射
- Java反射—初探反射基礎Java反射
- Java 反射 APIJava反射API
- Java 反射原理Java反射
- Java的反射Java反射
- 20201209——java反射Java反射
- 淺析Java反射--JavaJava反射
- Java筆記-Java反射(二)Java筆記反射
- Java基礎系列—Java反射Java反射
- Java 反射基礎Java反射
- Java反射-註解Java反射
- Java學習:反射Java反射
- Java反射-屬性Java反射
- Java反射-模組Java反射
- Java 反射詳解Java反射
- 秒懂Java反射Java反射
- java反射技術Java反射
- java反射全解Java反射
- Java 反射簡介Java反射
- java反射詳解Java反射
- Java筆記-反射Java筆記反射
- 淺析JAVA反射Java反射
- Java 方法的反射Java反射
- Java反射機制Java反射
- JAVA反射舉例Java反射
- [Java基礎]反射Java反射
- Java學習_反射Java反射
- Java基礎 —— 反射Java反射
- 【Java面試指北】反射(1) 初識反射Java面試反射
- JAVA-註解(2)-自定義註解及反射註解Java反射
- 【Java反射】Java 泛型基礎Java反射泛型
- Java反射與hook混用反射某支付的方法Java反射Hook
- java反射構建物件和方法的反射呼叫Java反射物件
- java反射學習(一)Java反射
- java利器——反射機制Java反射