java.lang.reflect 反射知識點 1

java.lang.reflect.Modifier

Modifier 類提供了 static 方法和常量,對類和成員訪問修飾符進行解碼。
修飾符集被表示爲整數,用不同的位位置 (bit position) 表示不同的修飾符。表示修飾符的常量值來自於 The JavaTM Virtual Machine Specification, Second edition 的表 4.1、4.4、4.5 和 4.7。

字段 說明 取值
ABSTRACT 表示 abstract 修飾符的 int 的值。 1024
FINAL 表示 final修飾符的 int 的值。 16
INTERFACE 表示 interface修飾符的 int 的值。 512
NATIVE 表示 native修飾符的 int 的值。 256
PRIVATE 表示 private修飾符的 int 的值。 2
PROTECTED 表示 protected修飾符的 int 的值。 4
PUBLIC 表示 public修飾符的 int 的值。 1
STATIC 表示 static修飾符的 int 的值。 8
STRICT 表示 strictfp修飾符的 int 的值。 2048
SYNCHRONIZED 表示 synchronized修飾符的 int 的值。 32
TRANSIENT 表示 transient修飾符的 int 的值。 128
VOLATILE 表示 volatile修飾符的 int 的值。 64

java.lang.reflect.Member

  • 提供類和接口,以獲取關於類和對象的反射信息。
  • 已知實現該接口的類有Method、Field、Constructor
  • Member接口是method、field、constructor對象識別信息
//用於標識【類】或【接口的所有公共成員的集合】,包括繼承成員
    public static final int PUBLIC = 0;
用於標識【類】或【接口的聲明成員集】。不包含繼承成員。

public static final int DECLARED = 1;

getDeclaringClass()

//返回表示類或接口的類對象(Class),該類或接口中由Meber聲明的成員或構造函數。
public Class<?> getDeclaringClass();

getName()

//返回此成員所表示的基礎成員或構造函數的簡單名稱
public String getName();

getModifiers()

//返回字段、構造函數的Java語言修飾符,返回值爲integer; 該修飾符可以使用Mofier類來解碼
public int getModifiers();

isSynthetic()

//如果該成員是由編譯器引入的,返回true;否則返回false 
public boolean isSynthetic();

java.lang.reflect.Type

沒有泛型的時候,只有原始類型。此時,所有的原始類型都通過字節碼文件類Class類進行抽象。Class類的一個具體對象就代表一個指定的原始類型
泛型出現之後,擴充了數據類型。從只有原始類型擴充了參數化類型、類型變量類型、限定符類型 、泛型數組類型。

  • Class(原始/基本類型,也叫raw type):不僅僅包含我們平常所指的類、枚舉、數組、註解,還包括基本類型int、float等等
  • TypeVariable(類型變量):比如List中的T等
  • WildcardType( 泛型表達式類型):例如List< ? extends Number>這種
  • ParameterizedType(參數化類型):就是我們平常所用到的泛型List、Map(注意和TypeVariable的區別)
  • GenericArrayType(數組類型):並不是我們工作中所使用的數組String[] 、byte[](這種都屬於Class),而是帶有泛型的數組,即T[] 泛型數組

Type接口本身算是一個標記接口,不提供任何需要複寫的方法

Type的直接子類只有一個,也就是Class,代表着類型中的原始類型以及基本類型。

public interface Type {
default String getTypeName() {
    return toString();
}

}

GenericArrayType(數組類型)

泛型數組,描述的是形如:A< T>[]或T[]類型變量和原始類型

public interface GenericArrayType extends Type {
//返回泛型數組中元素的Type類型,即List<String>[] 中的 List<String>
Type getGenericComponentType();

}

public class GenericArrayTypeTest<T> {

// 這裏面有各種各樣的數組:各有不同 方便看測試效果
// 含有泛型數組的纔是GenericArrayType
public void testGenericArrayType(List<String>[] pTypeArray, T[] vTypeArray, List<String> list,
                                 List<? extends Number> wildcardList, String[] strings, GenericArrayTypeTest[] test) {
}


public static void main(String[] args) {
    Method[] declaredMethods = GenericArrayTypeTest.class.getDeclaredMethods();
    for (Method method : declaredMethods) {
        // main方法不用處理
        if (method.getName().startsWith("main")) {
            continue;
        }

        // 開始處理該方法===打印出此方法簽名
        System.out.println("declare Method:" + method); //declare Method:public void com.fsx.maintest.GenericArrayTypeTest.testGenericArrayType(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[],com.fsx.maintest.GenericArrayTypeTest[])

        // 該方法能獲取到該方法所有的實際的參數化類型,比如本例中有五個參數,那數組長度就是5
        Type[] types = method.getGenericParameterTypes();

        // 分組打印出來
        for (Type type : types) {

            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                System.out.println("ParameterizedType type :" + parameterizedType);
            }
            else if (type instanceof GenericArrayType) {
                // 從結果

                GenericArrayType genericArrayType = (GenericArrayType) type;
                System.out.println("GenericArrayType type :" + genericArrayType);

                Type genericComponentType = genericArrayType.getGenericComponentType();
                System.out.println("genericComponentType:" + genericComponentType);
            }
            else if (type instanceof WildcardType) {
                WildcardType wildcardType = (WildcardType) type;
                System.out.println("WildcardType type :" + wildcardType);
            }
            else if (type instanceof TypeVariable) {
                TypeVariable typeVariable = (TypeVariable) type;
                System.out.println("TypeVariable type :" + typeVariable);
            }
            else {
                Class clazz = (Class) type;
                System.out.println("type :" + clazz);
            }
        }
    }
}

}

在這裏插入圖片描述

java.lang.reflect.AnnotatedElement

這個接口(AnnotatedElement)的對象代表了在當前JVM中的一個“被註解元素”(可以是Class,Method,Field,Constructor,Package等)。

在Java語言中,所有實現了這個接口的“元素”都是可以“被註解的元素”。使用這個接口中聲明的方法可以讀取(通過Java的反射機制)“被註解元素”的註解。這個接口中的所有方法返回的註解都是不可變的、並且都是可序列化的。這個接口中所有方法返回的數組可以被調用者修改,而不會影響其返回給其他調用者的數組。

子接口

  • AnnotatedArrayType (被註解的數組類型)
  • AnnotatedParameterizedType (被註解的參數化類型)
  • AnnotatedType (被註解的類型)
  • AnnotatedTypeVariable (被註解的類型變量)
  • AnnotatedWildcardType (被註解的通配類型)
  • GenericDeclaration (通用聲明,用於表示聲明型元素,如:類、方法、構造器等)
  • TypeVariable (類型變量)

實現類

  • AccessibleObject(可訪問對象,如:方法、構造器、屬性等)
  • Class(類,就是你用Java語言編程時每天都要寫的那個東西)
  • Constructor(構造器,類的構造方法的類型)
  • Executable(可執行的,如構造器和方法)
  • Field(屬性,類中屬性的類型)
  • Method(方法,類中方法的類型)
  • Package(包,你每天都在聲明的包的類型)
  • Parameter(參數,主要指方法或函數的參數,其實是這些參數的類型)

getAnnotationsByType(Class)和getDeclaredAnnotationsByType(Class)方法在一個元素上支持多個相同類型的註釋。

default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

如果指定類型的註解出現在當前元素上,則返回true,否則將返回false。這種方法主要是爲了方便地訪問一些已知的註解。

T getAnnotation(Class annotationClass)

如果在當前元素上存在參數所指定類型(annotationClass)的註解,則返回對應的註解,否則將返回null。

Annotation[] getAnnotations()

返回在這個元素上的所有註解。如果該元素沒有註釋,則返回值是長度爲0的數組。該方法的調用者可以自由地修改返回的數組;它不會對返回給其他調用者的數組產生影響。

default T[] getAnnotationsByType(Class annotationClass)

返回與該元素相關聯的註解。如果沒有與此元素相關聯的註解,則返回值是長度爲0的數組。這個方法與getAnnotation(Class)的區別在於,該方法檢測其參數是否爲可重複的註解類型(JLS 9.6),如果是,則嘗試通過“looking through”容器註解來查找該類型的一個或多個註解。該方法的調用者可以自由地修改返回的數組;它不會對返回給其他調用者的數組產生影響。參考@Repeatable。

  * @since 1.8
     */
    default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
         /*
          * Definition of associated: directly or indirectly present OR
          * neither directly nor indirectly present AND the element is
          * a Class, the annotation type is inheritable, and the
          * annotation type is associated with the superclass of the
          * element.
          */
         T[] result = getDeclaredAnnotationsByType(annotationClass);

         if (result.length == 0 && // Neither directly nor indirectly present
             this instanceof Class && // the element is a class
             AnnotationType.getInstance(annotationClass).isInherited()) { // Inheritable
             Class<?> superClass = ((Class<?>) this).getSuperclass();
             if (superClass != null) {
                 // Determine if the annotation is associated with the
                 // superclass
                 result = superClass.getAnnotationsByType(annotationClass);
             }
         }

         return result;
     }

default T getDeclaredAnnotation(Class annotationClass)

如果參數中所指定類型的註解是直接存在於當前元素上的,則返回對應的註解,否則將返回null。這個方法忽略了繼承的註解。(如果沒有直接在此元素上顯示註釋,則返回null。)

default T[] getDeclaredAnnotationsByType(Class annotationClass)

如果參數中所指定類型的註解是直接存在或間接存在於當前元素上的,則返回對應的註解。這種方法忽略了繼承的註釋。如果沒有直接或間接地存在於此元素上的指定註解,則返回值是長度爲0的數組。這個方法和getDeclaredAnnotation(Class)的區別在於,這個方法檢測它的參數是否爲可重複的註釋類型(JLS 9.6),如果是,則嘗試通過“looking through”容器註解來查找該類型的一個或多個註解。該方法的調用者可以自由地修改返回的數組;它不會對返回給其他調用者的數組產生影響。參考@Repeatable。

Annotation[] getDeclaredAnnotations()

返回直接出現在這個元素上的註解。這種方法忽略了繼承的註解。如果在此元素上沒有直接存在的註解,則返回值是長度爲0的數組。該方法的調用者可以自由地修改返回的數組;它不會對返回給其他調用者的數組產生影響。

Java 註解繼承

java.lang.annotation.Inherited

首先這個註解是javaAPI四個元註解之一,用於修飾註解,位於java.lang.annotation包下。

僅用於標識一個註解,背標識過的註解可以被繼承使用。

註解@A 使用了@Inherited 。@A使用到了接口B,接口B被C繼承實現,在C中可以獲取到註解@A的信息,如果 註解@A 沒有使用@Inherited C中則不能獲取到接口B的@A註解信息

註解的繼承

實際上Java註解可以進行繼承(也就是把多個註解合併成1個)

比如說SpringMVC的註解

@RestController
@RequestMapping("/person")
可以合併爲一個
@PathRestController("/user")
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章