深入理解反射機制(Java)

關於反射:

動態加載一個指定的類,獲取該類中的所有內容。並將字節碼文件中的內容都封裝成對象,便於操作這些成員。

反射機制允許程序在執行期藉助於Reflection API取得任何類的內部信息,並能直接操作任意對象的內部屬性及方法

 

反射的好處:大大的增強了程序的擴展性。

 

Java反射機制提供的功能:

    • 判斷任意一個對象所屬的類、構造任意一個類的對象、判斷任意一個類所具有的成員變量和方法、調用任意一個對象的成員變量和方法
    • Class對象,獲取類的Fields、獲取類的Method、獲取類的Constructor

 

 

1.理解Class類並實例化Class類對象

2.運行時創建類對象並獲取類的完整結構

3.通過反射調用類的指定方法、指定屬性

4.動態代理

 

 

主要提供用途:

1.   在運行時判斷任意一個對象所屬的類

2.   在運行時構造任意一個類的對象

3.   在運行時判斷任意一個類所具有的成員變量和方法

4.   在運行時調用任意一個對象的方法

 

 

反射的應用:

動態代理

 

反射的缺點:

Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.

儘管反射非常強大,但也不能濫用。如果一個功能可以不用反射完成,那麼最好就不用。

在用反射技術時,下面幾條內容應該牢記於心:

1.性能

反射包括了一些動態類型,所以 JVM 無法對這些代碼進行優化。因此,反射操作的效率要比那些非反射操作低得多。應該避免在經常被執行的代碼或對性能要求很高的程序中使用反射。

2.安全限制:

使用反射技術要求程序必須在一個沒有安全限制的環境中運行。如果一個程序必須在有安全限制的環境中運行,如 Applet,那麼這就是個問題了。

3.內部暴露 :

由於反射允許代碼執行一些在正常情況下不被允許的操作(比如訪問私有的屬性和方法),所以使用反射可能會導致意料之外的副作用--代碼有功能上的錯誤,降低可移植性。

4.反射代碼破壞了抽象性:

當平臺發生改變的時候,代碼的行爲就有可能也隨着變化。

 

反射慢的原因可能有?

1.      因爲接口的通用性,Java的invoke方法是傳object和object[]數組的。基本類型參數需要裝箱和拆箱,產生大量額外的對象和內存開銷,頻繁促發GC。

2.      編譯器難以對動態調用的代碼提前做優化,比如方法內聯。

3.      反射需要按名檢索類和方法,有一定的時間開銷

 

 

每個.class文件被加載到內存後都是一個Class類的對象!如Demo.class加載到內存後它是Class<Demo>類型的一個對象

反射就是通過Class對象獲取類型相關的信息。一個Class對象就表示一個.class文件,可以通過Class對象獲取這個類的構造器、方法,以及成員變量等。

 

java.lang.reflect包下:(反射相關類)

Constructor 類 提供一個類的構造函數的信息以及訪問類的構造函數的接口。

Method 類  提供一個類的方法的信息以及訪問類的方法的接口。

Field 類  提供一個類的域的信息以及訪問類的域的接口。

Modifier類 提供了 static 方法和常量,對類和成員訪問修飾符進行解碼。

Proxy 類  提供動態地生成代理類和類實例的靜態方法。

Member接口 該接口可以獲取有關類成員(域或者方法)後者構造函數的信息。

AccessibleObject 類 該類是域(field)對象、方法(method)對象、構造函數(constructor)對象的基礎類。它提供了將反射的對象標記爲在使用時取消默認 Java 語言訪問控制檢查的能力。

Array 類  該類提供動態地生成和訪問 JAVA 數組的方法。

 

 

類裝載器ClassLoader:尋找類的節碼文件並構造出類在JVM內部表示對象的組件,負責在運行時查找和裝入class字節碼文件。類裝載工作由ClassLoader以及其子類負責。

 

 

關於Class類(Java.lang.Class):

源程序通過編譯(javac.exe),生成對應的.class文件,用java.exe加載(.class文件加載入內存,就是一個運行時類,放在緩存區中)每一個運行時類只加載一次

有了Class實例後,可以如下操作:

創建對應的運行時類的對象

獲取對應的運行時類的完整結構(屬性,方法,構造器,內部類,父類,所在的包,異常,註釋。。。)

調用對應的運行時類的指定結構(屬性,方法,構造器)

 

使用Class<T>的函數newInstance或Constructor對象的newInstance

 

反射的基本步驟:

1、獲得Class對象,就是獲取到指定的名稱的字節碼文件對象。

2、實例化對象,獲得類的屬性、方法或構造函數。

3、訪問屬性、調用方法、調用構造函數創建對象。

 

獲取Class類的基本方式

1.通過類名稱.class:(基本數據類型和引用數據類型)都有一個靜態的屬性class。弊端:必須要先明確該類

Class c = int.class

Class c = int[].class;

Class c = String.class

2.通過對象.getClass()方法: 弊端:必須要創建該類對象,纔可以調用getClass方法

Class c = obj.getClass();

3.Class.forName()通過類名稱加載類,這種方法只要有類名稱就可以得到Class;擴展性最強,只要將類名字符串傳入

Class c = Class.forName(“com.jinwen.Demo”);

4.包裝類的方式(僅包裝類):

Class<?> classtype = Boolean.TYPE; 注意:這裏返回的是原生類型,和Boolean.class返回的不同

源碼可知:

public static final Class<Double>   TYPE = (Class<Double>) Class.getPrimitiveClass("double");

 

5.通過類加載器加載的方式:

ClassLoader load = Thread.currentThread().getContextClassLoader();

Class clazz = loader.loadClass(“com.jinwen.Demo”);

 

根據Class創建對象的方式

1,調用空參數的構造函數:使用了Class類中的newInstance()方法。

2,調用帶參數的構造函數:先要獲取指定參數列表的構造函數對象,然後通過該構造函數的對象的newInstance(實際參數) 進行對象的初始化。

//獲取一個帶參數的構造器。

Constructor constructor = clazz.getConstructor(String.class,int.class);

 

 

Class類源碼分析:

public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement {

屬性:

private static final int ANNOTATION= 0x00002000;
private static final int
ENUM      = 0x00004000;
private static final int
SYNTHETIC = 0x00001000;

private transient String name;

 

static {
    registerNatives()
;
}

構造方法:

private Class(ClassLoader loader) {
   
// Initialize final field for classLoader.  The initialization value of non-null prevents future JIT optimizations from assuming this final field is null.
   
classLoader = loader;
}

forName方法:

@CallerSensitive
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{
    Class<?> caller =
null;
   
SecurityManager sm = System.getSecurityManager();
    if
(sm != null) {
       
// Reflective call to get caller class is only needed if a security manager
        // is present.  Avoid the overhead of making this call otherwise.
       
caller = Reflection.getCallerClass();
        if
(sun.misc.VM.isSystemDomainLoader(loader)) {
            ClassLoader ccl = ClassLoader.getClassLoader(caller)
;
            if
(!sun.misc.VM.isSystemDomainLoader(ccl)) {
                sm.checkPermission(SecurityConstants.
GET_CLASSLOADER_PERMISSION);
           
}
        }
    }
   
return forName0(name, initialize, loader, caller);
}

private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class<?> caller)   throws ClassNotFoundException;

getName

獲取類名稱,包含包名

public String getName() {
    String name =
this.name;
    if
(name == null)
       
this.name = name = getName0();
    return
name;
}

private native String getName0();

getSimpleName

獲取類名稱,不包含包名

public String getSimpleName() {
   
if (isArray()) return getComponentType().getSimpleName()+"[]";
   
String simpleName = getSimpleBinaryName();
    if
(simpleName == null) { // top level class
       
simpleName = getName();
        return
simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name
   
}
    int length = simpleName.length();
    if
(length < 1 || simpleName.charAt(0) != '$')
       
throw new InternalError("Malformed class name");
    int
index = 1;
    while
(index < length && isAsciiDigit(simpleName.charAt(index)))
        index++
;
   
// Eventually, this is the empty string iff this is an anonymous class
   
return simpleName.substring(index);
}

getSuperclass

獲取父類的Class

public native Class<? super T> getSuperclass();

如:new Integer(100).getClass().getSupperClass()返回Class<Number>!但new Object().getSupperClass()返回的是null,因爲Object沒有父類;

newInstance:

使用本類無參構造器來創建本類對象
private volatile transient Constructor<T> cachedConstructor;

private volatile transient Class<?>       newInstanceCallerCache;

@CallerSensitive
public T newInstance() throws InstantiationException, IllegalAccessException{
   
if (System.getSecurityManager() != null) {
        checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), false);
   
}
   
// NOTE: the following code may not be strictly correct under the current Java memory model.
    // Constructor lookup
   
if (cachedConstructor == null) {
       
if (this == Class.class) {
          
throw new IllegalAccessException("Can not call newInstance() on the Class for java.lang.Class);
       
}
       
try {
            Class<?>[] empty = {}
;
            final
Constructor<T> c = getConstructor0(empty, Member.DECLARED);
           
// Disable accessibility checks on the constructor since we have to do the security check here anyway (the stack depth is wrong for the Constructor's security check to work)
           
java.security.AccessController.doPrivileged(
               
new java.security.PrivilegedAction<Void>() {
                    
public Void run() {
                           
c.setAccessible(true);
                            return null;
                       
}
                    })
;
           
cachedConstructor = c;
       
} catch (NoSuchMethodException e) {
            
throw (InstantiationException) new InstantiationException(getName()).initCause(e);
       
}
    }
    Constructor<
T> tmpConstructor = cachedConstructor;
   
// Security check (same as in java.lang.reflect.Constructor)
   
int modifiers = tmpConstructor.getModifiers();
    if
(!Reflection.quickCheckMemberAccess(this, modifiers)) {
        Class<?> caller = Reflection.getCallerClass()
;
        if
(newInstanceCallerCache != caller) {
            Reflection.ensureMemberAccess(caller
, this, null, modifiers);
           
newInstanceCallerCache = caller;
       
}
    }
   
// Run constructor
   
try {
       
return tmpConstructor.newInstance((Object[])null);
   
} catch (InvocationTargetException e) {
        Unsafe.getUnsafe().throwException(e.getTargetException())
;
       
// Not reached
       
return null;
   
}
}

getConstructor

通過指定的參數類型獲取公有構造器反射對象

@CallerSensitive
public Constructor<T> getConstructor(Class<?>... parameterTypes)
   
throws NoSuchMethodException, SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
    return
getConstructor0(parameterTypes, Member.PUBLIC);
}

獲取所有公有構造器對象

@CallerSensitive
public Constructor<?>[] getConstructors() throws SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
    return
copyConstructors(privateGetDeclaredConstructors(true));
}

獲取所有構造器對象。包含私有構造器

@CallerSensitive
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
    checkMemberAccess(Member.
DECLARED, Reflection.getCallerClass(), true);
    return
copyConstructors(privateGetDeclaredConstructors(false));
}

通過指定參數類型獲取構造器反射對象。包含私有構造器對象;

@CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
   
throws NoSuchMethodException, SecurityException {
    checkMemberAccess(Member.
DECLARED, Reflection.getCallerClass(), true);
    return
getConstructor0(parameterTypes, Member.DECLARED);
}

getField

可見 getFields 和 getDeclaredFields 區別:

getFields 返回的是申明爲 public 的屬性,包括父類中定義,

getDeclaredFields 返回的是指定類定義的所有定義的屬性,不包括父類的

 

通過名字獲取公有屬性反射對象,包含父類中聲明的公有屬性

@CallerSensitive
public Field getField(String name)
   
throws NoSuchFieldException, SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
   
Field field = getField0(name);
    if
(field == null) {
       
throw new NoSuchFieldException(name);
   
}
   
return field;
}

獲取所有公有屬性反射對象,包含父類中聲明的公有屬性

@CallerSensitive
public Field[] getFields() throws SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
    return
copyFields(privateGetPublicFields(null));
}

獲取本類中聲明的所有屬性,包含private屬性,但不包含父類中聲明的任何屬性
@CallerSensitive

public Field[] getDeclaredFields() throws SecurityException {

    checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);

    return copyFields(privateGetDeclaredFields(false));

}

通過名字獲取本類中某個屬性,包含本類private屬性,但父類中聲明的任何屬性都不包含

@CallerSensitive
public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException {
    checkMemberAccess(Member.
DECLARED, Reflection.getCallerClass(), true);
   
Field field = searchFields(privateGetDeclaredFields(false), name);
    if
(field == null) {
       
throw new NoSuchFieldException(name);
   
}
   
return field;
}

getMethod

通過方法名和方法參數類型獲取公有方法反射對象,包含父類中聲明的公有方法,但不包含所有私有方法

@CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes)
   
throws NoSuchMethodException, SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
   
Method method = getMethod0(name, parameterTypes, true);
    if
(method == null) {
       
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
   
}
   
return method;
}

獲取所有公有方法,包含父類中的公有方法,但不包含任何私有方法;

@CallerSensitive
public Method[] getMethods() throws SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
    return
copyMethods(privateGetPublicMethods());
}

通過方法名和方法參數類型獲取本類中聲明的所有方法的反射對象,但不包含父類中的任何方法

@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
   
throws NoSuchMethodException, SecurityException {
    checkMemberAccess(Member.
DECLARED, Reflection.getCallerClass(), true);

// privateGetDeclaredMethods方法從緩存或JVM中獲取該Class中申明的方法列表,searchMethods方法將從返回的方法列表裏找到一個匹配名稱和參數的方法對象
    Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
    if
(method == null) {
       
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
   
}
   
return method;
}

獲取本類中所有方法,包含本類中的私有方法,但不包含父類中的任何方法。

@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
    checkMemberAccess(Member.
DECLARED, Reflection.getCallerClass(), true);
    return
copyMethods(privateGetDeclaredMethods(false));
}

private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
    MethodArray interfaceCandidates =
new MethodArray(2);
   
Method res =  privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates);
    if
(res != null)
       
return res;
   
// Not found on class or superclass directly
   
interfaceCandidates.removeLessSpecifics();
    return
interfaceCandidates.getFirst(); // may be null
}

緩存JVM獲取Class中申明的方法列表

如果通過reflectionData()獲得的ReflectionData對象不爲空,則嘗試從ReflectionData對象中獲取declaredMethods屬性,如果是第一次,或被GC回收後,重新初始化後的類屬性爲空,則需重新到JVM中獲取一次,並賦值給ReflectionData,下次調用就可以使用緩存數據了。

private Method[] privateGetDeclaredMethods(boolean publicOnly) {
    checkInitted()
;
   
Method[] res;
   
ReflectionData<T> rd = reflectionData();  //數據結構ReflectionData,用來緩存從JVM中讀取類的一些屬性數據
    if (rd != null) {
        res = publicOnly ? rd.
declaredPublicMethods : rd.declaredMethods;
        if
(res != null) return res;
   
}
   
// No cached value available; request value from VM
   
res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
    if
(rd != null) {
       
if (publicOnly) {
            rd.
declaredPublicMethods = res;
       
} else {
            rd.
declaredMethods = res;
       
}
    }
   
return res;
}

private ReflectionData<T> reflectionData() {

// reflectionData對象是SoftReference類型的,說明在內存緊張時可能會被回收
    SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
    int
classRedefinedCount = this.classRedefinedCount;
   
ReflectionData<T> rd;
    if
(useCaches &&
        reflectionData !=
null &&
        (rd = reflectionData.get()) !=
null &&
        rd.
redefinedCount == classRedefinedCount) {
       
return rd;
   
}
   
// else no SoftReference or cleared SoftReference or stale ReflectionData
    // -> create and replace new instance
   
return newReflectionData(reflectionData, classRedefinedCount);
}

鏈接:主要存的是每次從jvm裏獲取到的一些類屬性,比如方法,字段等

private static class ReflectionData<T> {

    volatile Field[] declaredFields;

    volatile Field[] publicFields;

    volatile Method[] declaredMethods;

    volatile Method[] publicMethods;

    volatile Constructor<T>[] declaredConstructors;

    volatile Constructor<T>[] publicConstructors;

    // Intermediate results for getFields and getMethods

    volatile Field[] declaredPublicFields;

    volatile Method[] declaredPublicMethods;

    volatile Class<?>[] interfaces; 

    // Value of classRedefinedCount when we created this ReflectionData instance

    final int redefinedCount;

    ReflectionData(int redefinedCount) {

        this.redefinedCount = redefinedCount;

    }

}

如果reflectionData被回收之後,又執行了反射方法,那隻能通過newReflectionData方法重新創建一個這樣的對象
private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,
                                            int
classRedefinedCount) {
   
if (!useCaches) return null;
    while
(true) {
        ReflectionData<
T> rd = new ReflectionData<>(classRedefinedCount);
       
// try to CAS it...通過使用CAS重新設置reflectionData字段;
        if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {
           
return rd;
       
}
       
// else retry
       
oldReflectionData = this.reflectionData;
       
classRedefinedCount = this.classRedefinedCount;
        if
(oldReflectionData != null &&
            (rd = oldReflectionData.get()) !=
null &&
            rd.
redefinedCount == classRedefinedCount) {
           
return rd;
       
}
    }
}

 

private native Method[]      getDeclaredMethods0(boolean publicOnly);

searchMethods方法將從返回的方法列表裏找到一個匹配名稱和參數的方法對象

如果找到一個匹配的Method,則重新copy一份返回,即Method.copy()方法

getReflectionFactory().copyMethod(res))最終會調用Method的copy方法。所次每次調用getDeclaredMethod方法返回的Method對象其實都是一個新的對象,且新對象的root屬性都指向原來的Method對象,如果需要頻繁調用,最好把Method對象緩存起來

private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes){
    Method res =
null;
   
String internedName = name.intern();
    for
(int i = 0; i < methods.length; i++) {
        Method m = methods[i]
;
        if
(m.getName() == internedName
            && arrayContentsEq(parameterTypes
, m.getParameterTypes())
            && (res ==
null
               
|| res.getReturnType().isAssignableFrom(m.getReturnType())))
            res = m
;
   
}
   
return (res == null ? res : getReflectionFactory().copyMethod(res));
}

 

 

類類型相關方法:

boolean isArray():是否爲數組類型;

boolean isAnnotation():是否爲註解類型;

boolean isAnnotationPresent(Class annotationClass):當前類是否被annotationClass註解了;

boolean isEnum():是否爲枚舉類型;

boolean isInterface():是否爲接口類型;

boolean isPrimitive():是否爲基本類型;

boolean isSynthetic():是否爲引用類型;

 

 

實例

String className = "cn.jinwen.com.User";

Class clazz = Class.forName(className);

User user = (User)clazz.newInstance();

System.out.println(user);

 

 

關於AccessibleObject類:

AccessibleObject類是Constructor、Method、Field三個類的父類。

當Constructor、Method、Field爲私有時,如果我們想反射操作,那麼就必須先調用反射對象的setAccessible(true)方法,然後才能操作。

 

AccessibleObject源碼分析:

public class AccessibleObject implements AnnotatedElement {

static final private java.security.Permission ACCESS_PERMISSION =
       
new ReflectPermission("suppressAccessChecks");

setAccessible(boolean flag):

設置當前成員是否可訪問
    public static void setAccessible(AccessibleObject[] array, boolean flag)
       
throws SecurityException {
        SecurityManager sm = System.getSecurityManager()
;
        if
(sm != null) sm.checkPermission(ACCESS_PERMISSION);
        for
(int i = 0; i < array.length; i++) {
            setAccessible0(array[i]
, flag);
       
}
    }

    public void setAccessible(boolean flag) throws SecurityException {
        SecurityManager sm = System.getSecurityManager()
;
        if
(sm != null) sm.checkPermission(ACCESS_PERMISSION);
       
setAccessible0(this, flag);
   
}
    private static void setAccessible0(AccessibleObject obj, boolean flag) throws SecurityException {
       
if (obj instanceof Constructor && flag == true) {
            Constructor<?> c = (Constructor<?>)obj
;
            if
(c.getDeclaringClass() == Class.class) {
               
throw new SecurityException("Cannot make a java.lang.Class constructor accessible");
           
}
        }
        obj.
override = flag;
   
}

isAccessible():

判斷當前成員是否可訪問
    public boolean isAccessible() {
       
return override;
   
}

構造方法

protected AccessibleObject() {}
    boolean override;
    static final ReflectionFactory reflectionFactory = AccessController.doPrivileged(
           
new sun.reflect.ReflectionFactory.GetReflectionFactoryAction());

getAnnotation

public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
       
throw new AssertionError("All subclasses should override this method");
   
}
    @Override
   
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
       
return AnnotatedElement.super.isAnnotationPresent(annotationClass);
   
}
    @Override
   
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
       
throw new AssertionError("All subclasses should override this method");
   
}
    public Annotation[] getAnnotations() {
       
return getDeclaredAnnotations();
   
}
    @Override
   
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
        return getAnnotation(annotationClass);
   
}
    @Override
   
public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
        return getAnnotationsByType(annotationClass);
   
}
    public Annotation[] getDeclaredAnnotations()  {
       
throw new AssertionError("All subclasses should override this method");
   
}

checkAccess

volatile Object securityCheckCache;
    void
checkAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers) throws IllegalAccessException {
       
if (caller == clazz) {  // quick check
           
return;             // ACCESS IS OK
       
}
        Object cache =
securityCheckCache// read volatile
       
Class<?> targetClass = clazz;
        if
(obj != null
           
&& Modifier.isProtected(modifiers)
            && ((targetClass = obj.getClass()) != clazz)) {

            if (cache instanceof Class[]) {
                Class<?>[] cache2 = (Class<?>[]) cache
;
                if
(cache2[1] == targetClass &&
                    cache2[
0] == caller) {
                   
return;     // ACCESS IS OK
               
}
            }
        }
else if (cache == caller) {
            return;             // ACCESS IS OK
       
}
        slowCheckMemberAccess(caller, clazz, obj, modifiers, targetClass);
   
}
    void slowCheckMemberAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers, Class<?> targetClass) throws IllegalAccessException {
        Reflection.ensureMemberAccess(caller
, clazz, obj, modifiers);
        Object cache = ((targetClass == clazz)? caller : new Class<?>[] { caller, targetClass });
        securityCheckCache = cache;         // write volatile
   
}
}

 

 

 

關於Constructor類(java.lang.reflect):基於JDK8

Constructor表示一個類的構造器。即構造器的反射對象

 

獲取Constructor對象:

獲取Construcator對象需要使用Class對象

Constructor getConstructor(Class… parameterTypes):通過指定的參數類型獲取公有構造器反射對象;

Constructor[] getConstructors():獲取所有公有構造器對象;

Constructor getDeclaredConstructor(Class… parameterTypes):通過指定參數類型獲取構造器反射對象。可以是私有構造器對象;

Constructor[] getDeclaredConstructors():獲取所有構造器對象。包含私有構造器;

 

Constructor源碼分析

public final class Constructor<T> extends Executable {

屬性:

private Class<T>            clazz;
private int                
slot;
private
Class<?>[]          parameterTypes;
private
Class<?>[]          exceptionTypes;
private int                
modifiers;
// Generics and annotations support
private transient String    signature;
// generic info repository; lazily initialized
private transient ConstructorRepository genericInfo;
private byte
[]              annotations;
private byte
[]              parameterAnnotations;

構造方法:

Constructor(Class<T> declaringClass, Class<?>[] parameterTypes, Class<?>[] checkedExceptions, int modifiers, int slot, String signature, byte[] annotations, byte[] parameterAnnotations) {
   
this.clazz = declaringClass;
    this
.parameterTypes = parameterTypes;
    this
.exceptionTypes = checkedExceptions;
    this
.modifiers = modifiers;
    this
.slot = slot;
    this
.signature = signature;
    this
.annotations = annotations;
    this
.parameterAnnotations = parameterAnnotations;
}

getName

獲取構造器名

@Override
public String getName() {
   
return getDeclaringClass().getName();
}

getDeclaringClass

獲取構造器所屬的類型

@Override
public Class<T> getDeclaringClass() {
   
return clazz;
}

getParameterTypes

獲取構造器的所有參數的類型

@Override
public Class<?>[] getParameterTypes() {
   
return parameterTypes.clone();   // 返回的是副本
}

@Override
public Type[] getGenericParameterTypes() {
   
return super.getGenericParameterTypes();
}

public int getParameterCount() { return parameterTypes.length; }

getExceptionTypes

獲取構造器上聲明的所有異常類型

@Override
public Class<?>[] getExceptionTypes() {
   
return exceptionTypes.clone();
}

@Override
public Type[] getGenericExceptionTypes() {
   
return super.getGenericExceptionTypes();
}

newInstance

通過構造器反射對象調用構造器

@CallerSensitive
public T newInstance(Object ... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
   
if (!override) {
       
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass()
;
           
checkAccess(caller, clazz, null, modifiers);
       
}
    }
   
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
       
throw new IllegalArgumentException("Cannot reflectively create enum objects");
   
ConstructorAccessor ca = constructorAccessor;   // read volatile
   
if (ca == null) {
        ca = acquireConstructorAccessor()
;
   
}
   
@SuppressWarnings("unchecked")
   
T inst = (T) ca.newInstance(initargs);
    return
inst;
}

 

 

實例:

         String className = "cn.jinwen.www.User";

         Class clazz = Class.forName(className);

         Constructor c = clazz.getConstructor(String.class, String.class);

         User user = (User)c.newInstance("zhangSan", "123");

         System.out.println(user);

 

 

關於Method類(java.lang.reflect)

 

 

獲取Method:

獲取Method需要通過Class對象

Method getMethod(String name, Class… parameterTypes):通過方法名和方法參數類型獲取方法反射對象,包含父類中聲明的公有方法,但不包含所有私有方法;

Method[] getMethods():獲取所有公有方法,包含父類中的公有方法,但不包含任何私有方法;

Method getDeclaredMethod(String name, Class… parameterTypes):通過方法名和方法參數類型獲取本類中聲明的方法的反射對象,包含本類中的私有方法,但不包含父類中的任何方法;

Method[] getDeclaredMethods():獲取本類中所有方法,包含本類中的私有方法,但不包含父類中的任何方法。

 

 

 

Method源碼分析:

public final class Method extends Executable {

屬性

    private Class<?>            clazz;
    private int                
slot;
   
// This is guaranteed to be interned by the VM in the 1.4
    // reflection implementation
   
private String              name;
    private
Class<?>            returnType;
    private
Class<?>[]          parameterTypes;
    private
Class<?>[]          exceptionTypes;
    private int                
modifiers;
    
// Generics and annotations support
   
private transient String              signature;
   
// generic info repository; lazily initialized
   
private transient MethodRepository genericInfo;
    private byte
[]              annotations;
    private byte
[]              parameterAnnotations;
    private byte
[]              annotationDefault;
    private volatile
MethodAccessor methodAccessor;
   
// For sharing of MethodAccessors. This branching structure is
    // currently only two levels deep (i.e., one root Method and
    // potentially many Method objects pointing to it.)
    //
    // If this branching structure would ever contain cycles, deadlocks can
    // occur in annotation code.
   
private Method              root;

構造方法

Method(Class<?> declaringClass, String name, Class<?>[] parameterTypes, Class<?> returnType, Class<?>[] checkedExceptions, int modifiers, int slot, String signature, byte[] annotations, byte[] parameterAnnotations, byte[] annotationDefault) {
   
this.clazz = declaringClass;
    this
.name = name;
    this
.parameterTypes = parameterTypes;
    this
.returnType = returnType;
    this
.exceptionTypes = checkedExceptions;
    this
.modifiers = modifiers;
    this
.slot = slot;
    this
.signature = signature;
    this
.annotations = annotations;
    this
.parameterAnnotations = parameterAnnotations;
    this
.annotationDefault = annotationDefault;
}

copy

Method copy() {

    if (this.root != null)

        throw new IllegalArgumentException("Can not copy a non-root Method");

    Method res = new Method(clazz, name, parameterTypes, returnType,

                            exceptionTypes, modifiers, slot, signature,

                            annotations, parameterAnnotations, annotationDefault);

    res.root = this;

    // Might as well eagerly propagate this if already present

    res.methodAccessor = methodAccessor;

    return res;

}

getName

獲取方法名

@Override
public String getName() {
   
return name;
}

getDeclaringClass

獲取方法所屬的類型

@Override
public Class<?> getDeclaringClass() {
   
return clazz;
}

getParameterTypes

獲取方法的所有參數的類型

@Override
public Class<?>[] getParameterTypes() {
   
return parameterTypes.clone();
}

public int getParameterCount() { return parameterTypes.length; }

@Override
public Type[] getGenericParameterTypes() {
   
return super.getGenericParameterTypes();
}

getExceptionTypes

獲取方法上聲明的所有異常類型

@Override
public Class<?>[] getExceptionTypes() {
   
return exceptionTypes.clone();
}

@Override
public Type[] getGenericExceptionTypes() {
   
return super.getGenericExceptionTypes();
}

getReturnType

獲取方法的返回值類型

public Class<?> getReturnType() {
   
return returnType;
}

invoke

Method 類的 invoke 方法的具體實現方式。invoke 方法內部有兩種實現方式,一種是 native 原生的實現方式,一種是 Java 實現方式,這兩種各有千秋。而爲了最大化性能優勢,JDK 源碼使用了代理的設計模式去實現最大化性能

反射對象調用方法,如果當前方法是實例方法,那麼當前對象就是obj,如果當前方法是static方法,那麼可以給obj傳遞null。args表示是方法的參數

@CallerSensitive
public Object invoke(Object obj, Object... args)  throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{

// 首先進行權限檢查
    if (!override) {
       
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass()
;
           
checkAccess(caller, clazz, obj, modifiers);
       
}
    }
    MethodAccessor ma =
methodAccessor;             // read volatile   MethodAccessor是接口
    if (ma == null) {
        ma = acquireMethodAccessor()
;              // 反射實現,接口對應的實例類

  }

// 最後調用了 MethodAccessor 接口的實現類的 invoke 方法進行進一步處理
    return ma.invoke(obj, args);
}

關於MethodAccessor接口(sun.reflect):

MethodAccessor 是一個接口,定義了方法調用的具體操作、

public interface MethodAccessor {
    Object invoke(Object obj
, Object[] args) throws IllegalArgumentException, InvocationTargetException;
}

MethodAccessor有三個具體的實現類:

sun.reflect.DelegatingMethodAccessorImpl:最終注入給MethodmethodAccessor的,也就是某個Method的所有的invoke方法都會調用到這個DelegatingMethodAccessorImpl.invoke,正如其名一樣的,是做代理的

sun.reflect.MethodAccessorImpl:實現主要是native實現的,而GeneratedMethodAccessorXXX是爲每個需要反射調用的Method動態生成的類,後的XXX是一個數字,不斷遞增的,且所有的方法反射都是先走NativeMethodAccessorImpl,默認調了15次之後,才生成一個GeneratedMethodAccessorXXX類,生成好之後就會走這個生成的類的invoke方法了

sun.reflect.NativeMethodAccessorImpl:

 

MethodAccessor 對象其實就是具體去生成反射類的入口

查看MethodAccessor源碼上的註釋,我們可以瞭解到 MethodAccessor 對象的一些設計信息。

"Inflation" mechanism. Loading bytecodes to implement Method.invoke() and Constructor.newInstance() currently costs 3-4x more than an invocation via native code for the first invocation (though subsequent invocations have been benchmarked to be over 20x faster).Unfortunately this cost increases startup time for certain applications that use reflection intensively (but only once per class) to bootstrap themselves.

Inflation 機制。初次加載字節碼實現反射,使用 Method.invoke() 和 Constructor.newInstance() 加載花費的時間是使用原生代碼加載花費時間的 3 - 4 倍。這使得那些頻繁使用反射的應用需要花費更長的啓動時間

To avoid this penalty we reuse the existing JVM entry points for the first few invocations of Methods and Constructors and then switch to the bytecode-based implementations. Package-private to be accessible to NativeMethodAccessorImpl and NativeConstructorAccessorImpl.

爲了避免這種痛苦的加載時間,我們在第一次加載的時候重用了 JVM 的入口,之後切換到字節碼實現的實現。

 

實際的 MethodAccessor 實現有兩個版本,一個是 Native 版本,一個是 Java 版本。

Native 版本一開始啓動快,但是隨着運行時間邊長,速度變慢。Java 版本一開始加載慢,但是隨着運行時間邊長,速度變快。正是因爲兩種存在這些問題,所以第一次加載的時候我們會發現使用的是 NativeMethodAccessorImpl 的實現,而當反射調用次數超過 15 次之後,則使用 MethodAccessorGenerator 生成的 MethodAccessorImpl 對象去實現反射

// 返回MethodAccessor接口的實現類(通過工廠類實現)

先判斷是否存在對應的 MethodAccessor 對象,如果存在那麼就複用之前的 MethodAccessor 對象,否則調用 ReflectionFactory 對象的 newMethodAccessor 方法生成一個 MethodAccessor 對象。

private MethodAccessor acquireMethodAccessor() {
   
// First check to see if one has been created yet, and take it
    // if so
   
MethodAccessor tmp = null;
    if
(root != null) tmp = root.getMethodAccessor();
    if
(tmp != null) {
       
methodAccessor = tmp;
   
} else {
       
// Otherwise fabricate one and propagate it up to the root
       
tmp = reflectionFactory.newMethodAccessor(this);   // ReflectionFactory工廠實例化一個實現MethodAccessor接口的對象
        setMethodAccessor(tmp);
   
}
   
return tmp;
}

ReflectionFactory工廠類

http://upload-images.jianshu.io/upload_images/2184951-cc95a89261b02171.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240

在 ReflectionFactory 類的 newMethodAccessor 方法裏,首先生成一個 NativeMethodAccessorImpl 對象,再這個對象作爲參數調用 DelegatingMethodAccessorImpl 類的構造方法。

這裏使用代理模式,將 NativeMethodAccessorImpl 對象交給 DelegatingMethodAccessorImpl 對象代理。

ReflectionFactory 類的 newMethodAccessor 方法最終返回 DelegatingMethodAccessorImpl 類對象。

 

在ReflectionFactory類中,有2個重要的字段:noInflation(默認false)和inflationThreshold(默認15),在checkInitted方法中可以通過-Dsun.reflect.inflationThreshold=xxx和-Dsun.reflect.noInflation=true對這兩個字段重新設置,而且只會設置一次;

如果noInflation爲false,方法newMethodAccessor都會返回DelegatingMethodAccessorImpl對象:

http://upload-images.jianshu.io/upload_images/2184951-4e12c4b088111f47.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240

DelegatingMethodAccessorImpl對象就是一個代理對象,負責調用被代理對象delegate的invoke方法,其中delegate參數目前是NativeMethodAccessorImpl對象,所以最終Method的invoke方法調用的是NativeMethodAccessorImpl對象invoke方法,實現如下:

http://upload-images.jianshu.io/upload_images/2184951-ebd0c029bbe607a4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240

而在 NativeMethodAccessorImpl 的 invoke 方法裏,其會判斷調用次數是否超過閥值(numInvocations)。如果超過該閥值,就生成另一個MethodAccessor 對象,並將原來 DelegatingMethodAccessorImpl 對象中的 delegate 屬性指向最新的 MethodAccessor 對象。

這裏用ReflectionFactory類中的inflationThreshold,當delegate調用了15次invoke方法後,如果繼續調用就通過MethodAccessorGenerator類的generateMethod方法生成MethodAccessorImpl對象,並設置爲delegate對象,這樣下次執行Method.invoke時,就調用新建的MethodAccessor對象的invoke()方法

 

注:

generateMethod方法在生成MethodAccessorImpl對象時,會在內存中生成對應的字節碼,並調用ClassDefiner.defineClass創建對應的class對象

http://upload-images.jianshu.io/upload_images/2184951-f95ee19f3018c7c1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240

在ClassDefiner.defineClass方法實現中,每被調用一次都會生成一個DelegatingClassLoader類加載器對象

http://upload-images.jianshu.io/upload_images/2184951-f02067dd49e5d95c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240

每次都生成新的類加載器,是爲了性能考慮,在某些情況下可以卸載這些生成的類,因爲類的卸載是只有在類加載器可以被回收的情況下才會被回收的,如果用了原來的類加載器,那可能導致這些新創建的類一直無法被卸載,從其設計來看本身就不希望這些類一直存在內存裏的,在需要的時候有就行了。

 

Q:併發導致垃圾類創建

NativeMethodAccessorImpl.invoke都是不加鎖的,意味着如果併發很高時,可能同時有很多線程進入到創建GeneratedMethodAccessorXXX類的邏輯裏,雖然說最終使用的其實只會有一個,但是這些開銷已然存在了,假如有1000個線程都進入到創建GeneratedMethodAccessorXXX的邏輯裏,那意味着多創建了999個無用的類,這些類會一直佔着內存,直到能回收Perm的GC發生纔會回收

 

 

實例

         Class clazz = Person.class;

         Method method = clazz.getMethod(methodName, new Class[]{paramClazz1, paramClazz2});

         method.invoke();

 

關於Field類(java.lang.reflect)

ield表示類的成員變量,可以是實例變量,也可以是靜態變量。

獲取Field對象:

獲取Field對象需要使用Class對象,下面是Class類的API:

Field getField(String name):通過名字獲取公有成員變量的反射對象,包含父類中聲明的公有成員變量;

Field[] getFields():獲取所有公有成員變量反射對象,包含父類中聲明的公有成員變量;

Field getDeclaredField(String name):通過名字獲取本類中某個成員變量,包含本類的private成員變量,但父類中聲明的任何成員變量都不包含;

Field[] getDeclaredFields():獲取本類中聲明的所有成員變量,包含private成員變量,但不包含父類中聲明的任何成員變量;

 

 

 

Field類源碼分析

public final class Field extends AccessibleObject implements Member {

屬性:

private Class<?>            clazz;
private int                
slot;
// This is guaranteed to be interned by the VM in the 1.4
// reflection implementation

private String              name;
private
Class<?>            type;
private int                
modifiers;
// Generics and annotations support
private transient String    signature;
// generic info repository; lazily initialized
private transient FieldRepository genericInfo;
private byte
[]              annotations;
// Cached field accessor created without override
private FieldAccessor fieldAccessor;
// Cached field accessor created with override
private FieldAccessor overrideFieldAccessor;
// For sharing of FieldAccessors. This branching structure is
// currently only two levels deep (i.e., one root Field and
// potentially many Field objects pointing to it.)
//
// If this branching structure would ever contain cycles, deadlocks can
// occur in annotation code.

private Field               root;

構造方法:

Field(Class<?> declaringClass, String name, Class<?> type, int modifiers, int slot, String signature, byte[] annotations){
   
this.clazz = declaringClass;
    this
.name = name;
    this
.type = type;
    this
.modifiers = modifiers;
    this
.slot = slot;
    this
.signature = signature;
    this
.annotations = annotations;
}

 

getName():

獲取成員變量名;

public String getName() {
   
return name;
}

getDeclaringClass():

獲取成員變量的類型;

public Class<?> getDeclaringClass() {
   
return clazz;
}

getType():

獲取當前成員變量的類型;

public Class<?> getType() {

    return type;

}

public Type getGenericType() {
   
if (getGenericSignature() != null)
       
return getGenericInfo().getGenericType();
    else
        return
getType();
}

get(Object obj):

獲取obj對象的成員變量的值;

@CallerSensitive

public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException{

    if (!override) {

        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {

            Class<?> caller = Reflection.getCallerClass();

            checkAccess(caller, clazz, obj, modifiers);

        }

    }

    return getFieldAccessor(obj).get(obj);

}
// 還有其他類型的,包括BooleanByteCharShortIntegerFloatLongDouble

@CallerSensitive

public boolean getBoolean(Object obj) throws IllegalArgumentException, IllegalAccessException{  
    if (!override) {

        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {

            Class<?> caller = Reflection.getCallerClass();

            checkAccess(caller, clazz, obj, modifiers);

        }

    }

    return getFieldAccessor(obj).getBoolean(obj);  // 僅此處不同

}

set(Object obj, Object value):

設置obj對象的成員變量值爲value;

@CallerSensitive
public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException{
   
if (!override) {
       
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass()
;
           
checkAccess(caller, clazz, obj, modifiers);
       
}
    }
    getFieldAccessor(obj).set(obj
, value);
}

@CallerSensitive
public void setBoolean(Object obj, boolean z) throws IllegalArgumentException, IllegalAccessException{
   
if (!override) {
       
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass()
;
           
checkAccess(caller, clazz, obj, modifiers);
        
}
    }
    getFieldAccessor(obj).setBoolean(obj
, z);
}

getAnnotation

public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
    Objects.requireNonNull(annotationClass)
;
    return
annotationClass.cast(declaredAnnotations().get(annotationClass));
}

@Override
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
    Objects.requireNonNull(annotationClass)
;
    return
AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
}

public Annotation[] getDeclaredAnnotations()  {
   
return AnnotationParser.toArray(declaredAnnotations());
}

private native byte[] getTypeAnnotationBytes0();

public AnnotatedType getAnnotatedType() {
   
return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),

sun.misc.SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()),this, getDeclaringClass(),getGenericType(),TypeAnnotation.TypeAnnotationTarget.FIELD);

 

實例:

Protected和private都需要setAccessible(true),否則將拋異常

         Field field = clazz.getField(fieldName);

         field.setAccessible(true);

         field.setObject(value);

 

用反射獲取泛型信息

爲了通過反射操作泛型以迎合實際開發的需要, Java新增了java.lang.reflect.ParameterizedType java.lang.reflect.GenericArrayTypejava.lang.reflect.TypeVariable java.lang.reflect.WildcardType幾種類型來代表不能歸一到Class類型但是又和原始類型同樣重要的類型.

類型

含義

ParameterizedType

一種參數化類型, 比如Collection<String>

GenericArrayType

一種元素類型是參數化類型或者類型變量的數組類型

TypeVariable

各種類型變量的公共接口

WildcardType

一種通配符類型表達式, 如? ? extends Number ? super Integer

用ParameterizedType來獲取泛型信息.

public class Client {

    private Map<String, Object> objectMap;

    public void test(Map<String, User> map, String string) {

    }

    public Map<User, Bean> test() {

        return null;

    }

    /**

     * 測試屬性類型

     */

    @Test

    public void testFieldType() throws NoSuchFieldException {

        Field field = Client.class.getDeclaredField("objectMap");

        Type gType = field.getGenericType();

        // 打印type與generic type的區別

        System.out.println(field.getType());

        System.out.println(gType);

        System.out.println("**************");

        if (gType instanceof ParameterizedType) {

            ParameterizedType pType = (ParameterizedType) gType;

            Type[] types = pType.getActualTypeArguments();

            for (Type type : types) {

                System.out.println(type.toString());

            }

        }

    }

    /**

     * 測試參數類型

     */

    @Test

    public void testParamType() throws NoSuchMethodException {

        Method testMethod = Client.class.getMethod("test", Map.class, String.class);

        Type[] parameterTypes = testMethod.getGenericParameterTypes();

        for (Type type : parameterTypes) {

            System.out.println("type -> " + type);

            if (type instanceof ParameterizedType) {

                Type[] actualTypes = ((ParameterizedType) type).getActualTypeArguments();

                for (Type actualType : actualTypes) {

                    System.out.println("\tactual type -> " + actualType);

                }

            }

        }

    }

    /**

     * 測試返回值類型

     */

    @Test

    public void testReturnType() throws NoSuchMethodException {

        Method testMethod = Client.class.getMethod("test");

        Type returnType = testMethod.getGenericReturnType();

        System.out.println("return type -> " + returnType);

        if (returnType instanceof ParameterizedType) {

            Type[] actualTypes = ((ParameterizedType) returnType).getActualTypeArguments();

            for (Type actualType : actualTypes) {

                System.out.println("\tactual type -> " + actualType);

            }

        }

    }

用反射獲取註解

 

 

動態代理:(見動態代理)

主要涉及的類爲java.lang.reflect包中的兩個接口,Proxy和InvocationHandler。

 

類的生命週期 (見JVM)

 

 

 

反射在工廠模式:

interface fruit{

    public abstract void eat();

}

class Apple implements fruit{

    public void eat(){

        System.out.println("Apple");

    }

}

class Orange implements fruit{

    public void eat(){

        System.out.println("Orange");

    }

}

// 構造工廠類

// 也就是說以後如果我們在添加其他的實例的時候只需要修改工廠類就行了

class Factory{

    public static fruit getInstance(String fruitName){

        fruit f=null;

        if("Apple".equals(fruitName)){

            f=new Apple();

        }

        if("Orange".equals(fruitName)){

            f=new Orange();

        }

        return f;

    }

}

class hello{

    public static void main(String[] a){

        fruit f=Factory.getInstance("Orange");

        f.eat();

    }

}

使用反射的工廠模式:

interfacefruit{

    public abstract void eat();

}

classAppleimplementsfruit{

    publicvoideat(){

        System.out.println("Apple");

    }

}

  

classOrangeimplementsfruit{

    publicvoideat(){

        System.out.println("Orange");

    }

}

  

classFactory{

    publicstaticfruit getInstance(String ClassName){

        fruit f=null;

        try{

            f=(fruit)Class.forName(ClassName).newInstance();

        }catch(Exception e) {

            e.printStackTrace();

        }

        returnf;

    }

}

classhello{

    publicstaticvoidmain(String[] a){

        fruit f=Factory.getInstance("Reflect.Apple");

        if(f!=null){

            f.eat();

        }

    }

}

 

 

相關鏈接:

1.你假笨:從一起GC血案談到反射原理

「深入Java」類型信息:RTTI和反射

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章