1. 程式人生 > >Java Reflection(二):Classes

Java Reflection(二):Classes

原文地址 作者: Jakob Jenkov 譯者:葉文海([email protected]
使用Java反射機制可以在執行時期檢查Java類的資訊,檢查Java類的資訊往往是你在使用Java反射機制的時候所做的第一件事情,通過獲取類的資訊你可以獲取以下相關的內容:
Class物件
類名
修飾符
包資訊
父類
實現的介面
構造器
方法
變數
註解

除了上述這些內容,還有很多的資訊你可以通過反射機制獲得,如果你想要知道全部的資訊你可以檢視相應的文件JavaDoc for java.lang.Class裡面有詳盡的描述。


在本節中我們會簡短的涉及上述所提及的資訊,上述的一些主題我們會使用單獨的章節進行更詳細的描述,比如這段內容會描述如何獲取一個類的所有方法或者指定方法,但是在單獨的章節中則會向你展示如何呼叫反射獲得的方法(Method Object),如何在多個同名方法中通過給定的引數集合匹配到指定的方法,在一個方法通過反射機制呼叫的時候會丟擲那些異常?如何準確的獲取getter/setter方法等等。本節的內容主要是介紹Class類以及你能從Class類中獲取哪些資訊。

Class物件

在你想檢查一個類的資訊之前,你首先需要獲取類的Class物件。Java中的所有型別包括基本型別(int, long, float等等),即使是陣列都有與之關聯的Class類的物件。如果你在編譯期知道一個類的名字的話,那麼你可以使用如下的方式獲取一個類的Class物件。

   Class myObjectClass = MyObject.class;

如果你在編譯期不知道類的名字,但是你可以在執行期獲得到類名的字串,那麼你則可以這麼做來獲取Class物件:

   String className = ... ;//在執行期獲取的類名字串
   Class class = Class.forName(className);

在使用Class.forName()方法時,你必須提供一個類的全名,這個全名包括類所在的包的名字。例如MyObject類位於com.jenkov.myapp包,那麼他的全名就是com.jenkov.myapp.MyObject。
如果在呼叫Class.forName()方法時,沒有在編譯路徑下(classpath)找到對應的類,那麼將會丟擲ClassNotFoundException。

類名

你可以從Class物件中獲取兩個版本的類名。

通過getName() 方法返回類的全限定類名(包含包名):

    Class aClass = ... //獲取Class物件,具體方式可見Class物件小節
    String className = aClass.getName();

如果你僅僅只是想獲取類的名字(不包含包名),那麼你可以使用getSimpleName()方法:

    Class aClass = ... //獲取Class物件,具體方式可見Class物件小節
    String simpleClassName = aClass.getSimpleName();

修飾符

可以通過Class物件來訪問一個類的修飾符,即public,private,static等等的關鍵字,你可以使用如下方法來獲取類的修飾符:

    Class  aClass = ... //獲取Class物件,具體方式可見Class物件小節
    int modifiers = aClass.getModifiers();

修飾符都被包裝成一個int型別的數字,這樣每個修飾符都是一個位標識(flag bit),這個位標識可以設定和清除修飾符的型別。
可以使用java.lang.reflect.Modifier類中的方法來檢查修飾符的型別:

    Modifier.isAbstract(int modifiers);
    Modifier.isFinal(int modifiers);
    Modifier.isInterface(int modifiers);
    Modifier.isNative(int modifiers);
    Modifier.isPrivate(int modifiers);
    Modifier.isProtected(int modifiers);
    Modifier.isPublic(int modifiers);
    Modifier.isStatic(int modifiers);
    Modifier.isStrict(int modifiers);
    Modifier.isSynchronized(int modifiers);
    Modifier.isTransient(int modifiers);
    Modifier.isVolatile(int modifiers);

包資訊

可以使用Class物件通過如下的方式獲取包資訊:

    Class  aClass = ... //獲取Class物件,具體方式可見Class物件小節
    Package package = aClass.getPackage();

通過Package物件你可以獲取包的相關資訊,比如包名,你也可以通過Manifest檔案訪問位於編譯路徑下jar包的指定資訊,比如你可以在Manifest檔案中指定包的版本編號。更多的Package類資訊可以閱讀java.lang.Package

父類

通過Class物件你可以訪問類的父類,如下例:

    Class superclass = aClass.getSuperclass();

可以看到superclass物件其實就是一個Class類的例項,所以你可以繼續在這個物件上進行反射操作。

實現的介面

可以通過如下方式獲取指定類所實現的介面集合:

   Class  aClass = ... //獲取Class物件,具體方式可見Class物件小節
   Class[] interfaces = aClass.getInterfaces();

由於一個類可以實現多個介面,因此getInterfaces();方法返回一個Class陣列,在Java中介面同樣有對應的Class物件。
注意:getInterfaces()方法僅僅只返回當前類所實現的介面。當前類的父類如果實現了介面,這些介面是不會在返回的Class集合中的,儘管實際上當前類其實已經實現了父類介面。

構造器

你可以通過如下方式訪問一個類的構造方法:

  Constructor[] constructors = aClass.getConstructors();

更多有關Constructor的資訊可以訪問Constructors

方法

你可以通過如下方式訪問一個類的所有方法:

  Method[] method = aClass.getMethods();

更多有關Method的資訊可以訪問Methods

變數

你可以通過如下方式訪問一個類的成員變數:

  Field[] method = aClass.getFields();

更多有關Field的資訊可以訪問Fields

註解

你可以通過如下方式訪問一個類的註解:

  Annotation[] annotations = aClass.getAnnotations();

更多有關Annotation的資訊可以訪問Annotations