Java源碼解析(2) —— Class(1)

Class —— 反射基石

  Java基本類之一,反射機制的基礎。其意義爲:類的抽象,即對“類”做描述:比如類有修飾、字段、方法等屬性,有獲得該類的所有方法、所有公有方法等方法。同時,Class也是Java類型中最重要的一種,表示原始類型(引用類型)及基本類型。

聲明

1.Class的源碼太長,這裏分4部分解析,一些方法的實現源代碼較長,這裏就沒有貼出來了,我會着重將敘述其作用,至於其實現邏輯,以本人現有水平估計也很難一一講解清晰,大家姑且看之,若其中有錯誤地方或未講解明白的可留言探討。
2.閱讀該文前,若對反射和泛型知識有一定基礎最好。

源碼

public final
    class Class<T> implements java.io.Serializable,
                            java.lang.reflect.GenericDeclaration,
                              java.lang.reflect.Type,
                              java.lang.reflect.AnnotatedElement {
    private static final int ANNOTATION= 0x00002000;//註釋類型
    private static final int ENUM      = 0x00004000;//枚舉類型
    private static final int SYNTHETIC = 0x00001000;//合成類型,注0
    //枚舉是一種類(class),註釋是一種接口(interface)
    private transient String name;//全限定名(包+類名)
    private native String getName0();//本地方法獲取name屬性
    //註冊本地方法
    private static native void registerNatives();
    static {
        registerNatives();
    }
    private Class() {}//唯一私有構造方法,說明Class不可由用戶構造實例
    public String toString() {
        //這裏重寫toString,只區別了接口和Class
        return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
            + getName();
    }
    //通過類全限定名獲得該類(或接口)的Class對象(加載該類)
    @CallerSensitive   //注1
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }
    @CallerSensitive
    public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)
        throws ClassNotFoundException
    {
        //initialize : 是否立即初始化該類,注2
        //loader : 使用指定的類加載器加載
    }
    private static native Class<?> forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class<?> caller)
        throws ClassNotFoundException;
    //反射獲得該類實例對象
 @CallerSensitive
    public T newInstance()
        throws InstantiationException, IllegalAccessException
    {
    //JDK明言:本方法在當前Java內存模型下不一定是正確的
        //反射獲取該類實例對象,實例化對象不是通過new指令,而是直接
        //通過本地方法獲取類的公有構造方法(無參),然後通過Constructor的
        //newInstance();方法實例化對象
        //這個過程還要檢查是否有權限反射實例化該對象
    }
    //緩存上面方法已獲取的公有構造方法,供下次使用
    private volatile transient Constructor<T> cachedConstructor;
    //緩存調用本方法的最初對象的類Class對象,供安全檢查使用,見注1
    private volatile transient Class<?>       newInstanceCallerCache;
    //判斷obj對象是否是該Class的實例
    public native boolean isInstance(Object obj);
    //判斷cls是否是調用者同一類型或其子類類型
    public native boolean isAssignableFrom(Class<?> cls);
    //判斷該Class是否是接口類型
    public native boolean isInterface();
    //判斷該Class是否是數組類型
    public native boolean isArray();
    //判斷該Class是否是基本類型,注3(八大基本類型+一特殊基本類型)
    public native boolean isPrimitive();
    //判斷該Class是否是註釋類型
    public boolean isAnnotation() {
        return (getModifiers() & ANNOTATION) != 0;
    }
    //判斷該Class是否是合成類型
    public boolean isSynthetic() {
        return (getModifiers() & SYNTHETIC) != 0;
    }
    public String getName() {
        String name = this.name;
        if (name == null)
            this.name = name = getName0();//通過本地方法獲取全路徑類名
        return name;
    }
    //獲取加載該類的類加載器
    @CallerSensitive
    public ClassLoader getClassLoader() {
        ClassLoader cl = getClassLoader0();
        if (cl == null)
            return null;
        SecurityManager sm = System.getSecurityManager();//注5
        if (sm != null) {
            ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
        }
        return cl;
    }
    native ClassLoader getClassLoader0();
    //返回該類中變量字段的類型變量數組,按聲明順序排序,注4
    public TypeVariable<Class<T>>[] getTypeParameters() {
        if (getGenericSignature() != null)
            return (TypeVariable<Class<T>>[])getGenericInfo().getTypeParameters();
        else
            return (TypeVariable<Class<T>>[])new TypeVariable<?>[0];
    }
    //獲得該類的直接父類的Class對象,如果該類是接口,則返回null
    public native Class<? super T> getSuperclass();
    //返回帶參數化類型的直接父類的類型
    public Type getGenericSuperclass() {}
    //獲取該類的包路徑
    public Package getPackage() {
        return Package.getPackage(this);
    }
    //獲取該類直接實現的所有接口
    public native Class<?>[] getInterfaces();
    //獲取所有接口,同上面的不同之處在於,若超接口是參數化類型(泛型)則返回的是其實際類型
    public Type[] getGenericInterfaces() {
        if (getGenericSignature() != null)
            return getGenericInfo().getSuperInterfaces();
        else
            return getInterfaces();
    }
    /**返回數組類型,若該類不是數組,返回null
     * 如:A[] a = new A[];
     * a.getClass().getComponentType()返回的是A類型(全路徑名) 
     */
    public native Class<?> getComponentType();
    //返回這個類的修飾符的對應的int值,二者可通過Modifier.toString()轉換
    public native int getModifiers();
    //獲取該類的所有簽名(標記)列表
    public native Object[] getSigners();
    //設置該類的簽名,注意方法修飾是默認,所以只有同包下類可用
    native void setSigners(Object[] signers);
    /**
     * 以上兩個方法不是很懂具體用來幹什麼的,估計是和安全檢查什麼有關,因爲
     * setSigners()是默認修飾,只能同包下訪問(這就是說,用戶是用不了的)
     */
}

注0:合成類型,參考:synthetic Java合成類型
注1:@CallerSensitive註解,參考:JVM註解@CallSensitive(HEL_WOR)
注2:類的初始化
  forName()方法默認是初始化類,不需要加載的的時候同時初始化類,需用forName的重載函數。類的加載、初始化可參考:Java類的加載
注3:Java基本數據類型
  除了8大基本類型,還有void,詳見:Java變量數據類型
注4:Java類型,詳見:Type Java類型
注5:關於Java安全策略之安全管理器,現可以參考:java安全沙箱(四)(xionghuiCoder)

概述

  Class類,表示Java的基礎類型(類+基本類型),是對Java類的抽象,描述的是類的信息,包括類的修飾符(public/private/protect/default/static/final等)、類的類型(一般類、枚舉、註釋、接口、數組等)、類的構造器、類的字段、類的方法等信息。所以在看待Class相關問題的時候應該從所有類的共性這個角度去看。注意,這裏的類不是平常我們說的狹義上的類(class),而是廣義上,包括了像接口、註釋、數組等類型的類,下面若不特殊聲明,類代表着廣義上的類。
  每一個類在JVM內存中,有一個唯一的對應的Class對象,這個對象有着該類的描述信息,所以運行時可以通過該Class類對象進行相應的操作,這就是Java的反射了。(Java基本類型也對應一個Class對象)

//獲得Class對象的方法
//1.通過 類型.class 獲得,適用於所有類型
Class str = String.class;
Class i = int.class;
Class d = Double[].class;
//2.通過 Object的getClass() 方法獲得,適用於所有非基本類型
A a = new A(); Class ac = a.getClass();
//3.通過 Class.forName(String name) 方法獲得
Class ac1 = Class.forName("com.fcc.test.A");//注意要用全限定名

源碼詳解

1.forName
  靜態方法,通過類的全限定名加載類,返回該類的Class對象,forName有兩個重載,forName(String)和forName(String, boolean, ClassLoader),其中,第一個參數是類的全限定名,第二個參數是指加載該類的後是否初始化該類,默認是加載後並初始化該類,最後一個參數是指使用哪個類加載器加載該類,默認是使用當前類的類加載器加載該類。
2.newInstance
  創建該Class對象對應的對象實例,只有當類具有公有的無參構造方法才能成功,否則拋異常,關於newInstance詳見:newInstance和new(編輯中)
3.getClassLoader
  獲得加載該類的類加載器,在本JVM(Oracle HotSopt),當本類的類加載器是引導類加載器(bootStrap)則返回的是null。(類的加載見上面注2。)
4.getTypeParameters
  返回該類中聲明(定義)的類變量數組,例如:

//關於TypeVariable詳見注3
public class Main<K, V> {
    public static void main(String[] args) throws Exception
    {
        Class cl = Main.class;
        TypeVariable[] types = cl.getTypeParameters();
        for(TypeVariable type : types){
            System.out.println(type.getName());
        }
    }
}
K
V

5.getSuperclass
  獲得該Class的直接父類對應的Class對象,如果該Class是基本類型(包括void,注意是小寫的關鍵字void,不是大寫的類Void)、接口、註釋,則返回null。

Class c0 = Main.class;//類,返回直接父類,泛型當做普通類處理
Class c1 = EnumA.class;//枚舉類型,默認繼承Enum類
Class c2 = int.class;//基本類型返回null
Class c3 = int[].class;//數組統一返回 class Object
Class c4 = InterfaceB.class;//接口也是返回null
Class c5 = Deprecated.class;//註釋類型也返回null,c5.isInterface() 爲true
System.out.println("類 : " + c0.getSuperclass());
System.out.println("枚舉 : " + c1.getSuperclass());
System.out.println("基本類型 : " + c2.getSuperclass());
System.out.println("數組 : " + c3.getSuperclass());
System.out.println("接口 : " + c4.getSuperclass());
System.out.println("註釋 : " + c5.getSuperclass());
//輸出結果
類 : class java.lang.Object
枚舉 : class java.lang.Enum
基本類型 : null
數組 : class java.lang.Object
接口 : null
註釋 : null

6.getGenericSuperclass
  獲得直接父類的類型,可以理解爲在5的基礎上,如果其是泛型,再獲得其類型原型(但需要繼承時顯式表示)。

public class Main<K, V> {
    public static void main(String[] args) throws Exception
    {
        Class c0 = ClassA.class;
        Class c1 = EnumA.class;//枚舉類型,默認繼承Enum類
        Class c2 = int.class;//基本類型返回null
        Class c3 = ClassA[].class;//數組統一返回 class Object
        Class c4 = InterfaceB.class;//接口也是返回null
        Class c5 = Deprecated.class;//註釋類型也返回null
        System.out.println("類 : " + c0.getGenericSuperclass());
        System.out.println("枚舉 : " + c1.getGenericSuperclass());
        System.out.println("基本類型 : " + c2.getGenericSuperclass());
        System.out.println("數組 : " + c3.getGenericSuperclass());
        System.out.println("接口 : " + c4.getGenericSuperclass());
        System.out.println("註釋 : " + c5.getGenericSuperclass());
        System.out.println(c2.isInterface());
    }
}
class ClassA<K,V> extends Main<K,V>{}//注1
//輸出結果
類 : com.fcc.test.Main<K, V>
枚舉 : java.lang.Enum<com.fcc.test.EnumA>
基本類型 : null
數組 : class java.lang.Object
接口 : null
註釋 : null1:如果是以下形式
class ClassA extends Main{}
則輸出爲:類 : com.fcc.test.Main

7.getInterfaces
8.getGenericInterfaces
  getInterfaces/getGenericInterfaces這一對同getSuperclass/getGenericSuperclass類似,getInterfaces/getGenericInterfaces前者是獲得該類直接實現的所有接口(不包括接口的父接口,也不包括父類實現的接口),後者是,如果接口是泛型,還原泛型的原型(但需要實現時顯式表示,這一點同getGenericSuperclass類似)。不過不管是哪一對,要注意,返回值類型的不同。

Class c0 = ClassB.class;
Class[] ifaces = c0.getInterfaces();
for(Class c : ifaces){
    System.out.println(c);
}
Type[] ifaces1 = c0.getGenericInterfaces();
for(Type c : ifaces1){
    System.out.println(c);
}
class ClassB<E> extends ClassA implements InterfaceB<E>{}
//輸出結果
interface com.fcc.test.InterfaceB
com.fcc.test.InterfaceB<E>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章