Java RTTI 和 反射
阿新 • • 發佈:2018-12-20
一、概念: RTTI(Run-Time Type Identification,執行時型別識別)的含義就是在執行時識別一個物件的型別,其對應的類是Class物件,怎麼理解這個Class物件呢?如果說類是所有物件方法、屬性的集合,那就可以把這個Class物件理解成是所有class的集合,然後利用這個Class物件動態的解析出相關類,並可以獲得其構造器和方法等,甚至例項化這個類的物件。開始文章前,先提重要的一點:無論是RTTI還是反射,其本質都是一樣的,都是去動態的獲取類的資訊,他們唯一的區別僅是:
- RTTI 在編譯期知道要解析的型別。
- 反射 在執行期知道要解析的型別。
二、RTTI
有以下兩種方式可以獲取到Class物件:
public static void main(String[] args)
{
try {
//第一種方式
Class rtti = Class.forName("com.jomoo.test.rtti.RTTI");
//第二種方式
Class type=RTTI.class;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
可以看到,採用RTTI的方式必須在寫程式的時候就知道了類的名字,才能獲取到Class物件對這個類的引用,並利用這個引用,得到大量關於這個類的資訊,包括介面,父類,方法,靜態成員,甚至是像newInstance()方法這樣的一個實現“虛擬構造器”的一種方式。
RTTI r =(RTTI)rtti.newInstance();//newInstance的類必須要有一個預設構造器
另外需要提一個經常用到 instanceof 該關鍵字的呼叫其實就是使用了Class物件,並且返回一個布林值。
Object o = rtti.newInstance();
if (o instanceof RTTI){
System.out.println(true);//這裡需要注意的是,如果 o 是 RTTI的子類的話,返回的也會true;
}
三、反射
Java中有時候在編譯器為程式生成程式碼很久之後才會出現要處理的那個類,那麼這個時候怎麼才能處理這個類呢,即在編譯的時候根本無法獲知這個物件所屬的類。答案就是利用Java的反射機制。廢話不多說,看完下面這個程式碼你就很清楚的明白 RTTI 和 反射的區別在哪裡了。
public class RTTI
{
private static final String usage="usage";
private static Pattern pattern=Pattern.compile("\\w+\\.");
public static void main(String[] args)
{
if (args.length<1){
System.out.println(usage);
System.exit(0);
}
int lines=0;
try {
Class c = Class.forName(args[0]);//看這裡類的名字在編譯的時候是無法得知的,只有在執行的時候動態傳進去
Method[] method = c.getMethods();
Constructor[] constructors = c.getConstructors();
if (args.length==1){
for (int i=0;i<method.length;i++){
System.out.println(pattern.matcher(method[i].toString()).replaceAll(""));
}
for (int i=0;i<constructors.length;i++){
System.out.println(pattern.matcher(constructors[i].toString()).replaceAll(""));
}
lines=method.length+constructors.length;
}else {
for (int i=0;i<method.length;i++){
if (method[i].toString().indexOf(args[1])!=-1){
System.out.println(pattern.matcher(method[i].toString()).replaceAll(""));
}
lines++;
}
for (int i=0;i<constructors.length;i++){
if (constructors[i].toString().indexOf(args[1])!=-1){
System.out.println(pattern.matcher(constructors[i].toString()).replaceAll(""));
}
lines++;
}
}
} catch (ClassNotFoundException e) {
System.out.println("NO!!!!");
}
}
}