欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文搞懂Java中的注解和反射

 更新時間:2022年06月21日 09:52:01   作者:靜守己心&笑淡浮華  
這篇文章主要給大家介紹了關于Java中注解和反射的原理及使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

1、注解(Annotation)

1.1 什么是注解(Annotation)

注解不是程序本身,可以在程序編譯、類加載和運行時被讀取,并執(zhí)行相應的處理。注解的格式為"@注釋名(參數值)",可以附加在包、類、方法和字段上,通過反射機制實現(xiàn)實現(xiàn)注解的訪問。

1.2 內置注解

@Override:限定子類重寫方法

該注解表示覆蓋的是其父類的方法,當子類重寫父類方法時,確保子類確實重寫了父類的方法,避免出現(xiàn)低級錯誤

/**
 * 該注解標識覆蓋的是其父類的方法,當子類重寫父類方法時,確保子類確實重寫了父類的方法,避免出現(xiàn)低級錯誤
 * @return
 */
@Override
public String toString() {
    return super.toString();
}

@Deprecated:標記已過時

該注解表示某個屬性、方法或類等已過時(程序員不鼓勵使用的程序元素,通常是因為它是危險的,或者因為存在更好的替代方法),當其他程序使用已過時的屬性、方法或者類時,編譯器會給出警告(刪除線)。

/**
 * 該注解表示此方法已過時,存在危險,不推薦使用,其有代替方法,如果繼續(xù)使用會通過刪除線進行標識
 */
@Deprecated
public static void test() {
    System.out.println("標記已過時");
}

@SuppressWarnings(參數):抑制編譯器警告

該注解作用的類、方法和屬性會取消顯示編譯器警告,其參數主要是進行警告說明以及取消(unchecked)等。

@SuppressWarnings("取消此類的所有警告")
public class BuiltAnnotation {
    
    @SuppressWarnings("取消此屬性的警告")
    private String username;

    @SuppressWarnings("取消此方法的警告")
    public static void main(String[] args) {
        // ...
    }
}

1.3 元注解(meta-annotation)

元注解的作用就是負責注解其他注解,Java定義了4個標準的元注解類型,他們被用來提供對其他注解的作用范圍及類型進行說明,通過元注解可以自定義其他注解。

@Target:描述注解的使用范圍

例如@Target(ElementType.METHOD)表示作用在方法上,@Target(ElementType.TYPE)表示作用在類或接口上等

/**
 * @Target注解:描述注解的使用范圍
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * 類或接口:ElementType.TYPE;
     * 字段:ElementType.FIELD;
     * 方法:ElementType.METHOD;
     * 構造方法:ElementType.CONSTRUCTOR;
     * 方法參數:ElementType.PARAMETER;
     * ...
     */
    ElementType[] value();
}

@Retention:表示需要在什么級別保存該注解信息,用于描述注解的生命周期

通常自定義的注解都使用@Retention(RetentionPolicy.RUNTIME),也就是運行時期作用。

/**
 * @Retention:表示需要在什么級別保存該注解信息,用于描述注解的生命周期
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * RetentionPolicy.SOURCE:僅編譯期,注解將被編譯器丟棄。
     * RetentionPolicy.CLASS:僅class文件,注釋將由編譯器記錄在類文件中,但VM不需要在運行時保留,如果不指定則默認為class。
     * RetentionPolicy.RUNTIME:運行期,注釋將由編譯器記錄在類文件中,并由VM在運行時保留,因此可以反射讀取。通常自定義的注解都是RUNTIME。
     * 范圍:RUNTIME>CLASS>SOURCE
     */
    RetentionPolicy value();
}

@Document:說明該注將被包含在javadoc中

@Iherited:定義子類是否可繼承父類定義的注解。

@Inherited僅針對 @Target(ElementType.TYPE) 類型的注解有用,并且只能是 class 的繼承,對 interface 的繼承無效:

1.4 自定義注解

定義注解

/**
 * 1. 使用@interface定義注解;
 * 3. 通過元注解配置該注解,配置注解的使用范圍和生命周期等
 * @author Loner
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Report{
    /**
     * 2. 添加參數、默認值,如果沒有默認值,就必須給參數賦值,一般把最常用的參數定義為value(),推薦所有參數都盡量設置默認值
     * 形式為:參數類型 參數名();
     */
    int type() default 0;
    String value() default "LonerMJ";
}

使用注解

@Report(type = 1, value = "test")
public class CustomerAnnotation {
    @Report(type = 1, value = "test")
    public void testCustomerAnnotation() {
        System.out.println("測試自定義注解");
    }
}

2、反射(Reflection)

2.1 反射和反射機制

反射

Reflection(反射)是指程序在運行期可以拿到一個對象的所有信息。

反射機制

反射機制是指程序在運行時,通過Reflection API獲取任何類的內容信息,并能直接操作任何對象的內部屬性及方法。

2.2 Class類的獲取方式和常用方法

java.lang.Class類,實現(xiàn)反射的核心類,類加載完成之后,在堆內存的方法區(qū)中就會產生一個Class對象(一個類只有一個Class對象),這個對象包含了類的完整結構信息,通過這個對象看到類的結構。

Class類的獲取方式

public class InstantiationClass {
    public static void main(String[] args) throws ClassNotFoundException {
        Teacher teacher = new Teacher("張三", "123456");

        // 方式一:調用Class類的靜態(tài)方法forName(String className)
        Class<?> c1 = Class.forName("com.loner.mj.reflection.Teacher");

        // 方式二:已知某個類的實例,調用該實例的getClass()方法,getClass是Object類中的方法。
        Class<? extends Teacher> c2 = teacher.getClass();

        // 方式三:已知具體類,通過類的class屬性獲取,該方法最安全可靠,程序性能最高
        Class<Teacher> c3 = Teacher.class;

        // 方式四:通過基本內置類型的包裝類的TYPE屬性獲得CLass實例
        Class<Integer> c4 = Integer.TYPE;

        // 方式五:通過當前子類的Class對象獲得父類的Class對象
        Class<?> c5 = c1.getSuperclass();
    }
}

Class類的常用方法

方法名方法功能
static Class forName(String name)返回指定類名的Class對象
Obiect newInstance()調用無參構造函數,返回Class對象的一個實例
String getName()返回此Class對象所表示的實體(類,接口,數組類或void)的名稱
Class getSuperclass()返回當前Class對象的父類的Class對象
Class[] getinterfaces()返回當前Class對象的接口
ClassLoader getClassLoader()返回該類的類加載器
Method getDeclareMethod(String name, Class<?> ... parameterTypes)獲取方法名和參數列表匹配的方法
Method[] getDeclareMethods()獲取所有非繼承的方法
Method[] getMethods()獲取所有非私有方法
Field getDeclareField(String name)獲取指定屬性
Field[] getDeclareFields()獲取所有屬性
Field[] getFields()獲取所有非私有屬性
Constructor getConstructor(Class<?>... parameterTypes獲取參數列表匹配的構造方法
Constructor getConstructors()獲取類的所有構造方法
A getAnnotation(Class<?> annotationClass)返回指定注解
Annotation[] getDeclaredAnnotations()返回所有注解
public class ReflectionMethods {
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
        Class<Worker> workerClass = Worker.class;

        /**
         * 類
         */
        System.out.println(workerClass.getName());
        System.out.println(workerClass.getSimpleName());
        System.out.println(workerClass.getSuperclass());
        System.out.println(workerClass.getPackage());
        Class<?>[] interfaces = workerClass.getInterfaces();
        for (Class<?> i : interfaces) {
            System.out.println(i);
        }

        /**
         * 屬性
         */
        // 獲取所有的屬性
        Field[] declaredFields = workerClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        // 獲取指定屬性
        System.out.println(workerClass.getDeclaredField("username"));
        // 獲取所有公共屬性
        Field[] fields = workerClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        /**
         * 構造方法
         */
        // 獲取所有構造方法
        Constructor<?>[] declaredConstructors = workerClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        // 獲取指定的構造方法
        System.out.println(workerClass.getDeclaredConstructor(String.class, String.class));

        /**
         * 方法
         */
        // 獲取所有的方法
        Method[] declaredMethods = workerClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        // 獲取指定方法
        System.out.println(workerClass.getDeclaredMethod("getUsername", null));
        // 獲取所有功能方法
        Method[] methods = workerClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}

哪些類型具有Class對象

public class InstantiationClass {
    public static void main(String[] args) throws ClassNotFoundException {
        // 類(外部類,成員(成員內部類,靜態(tài)內部類),局部內部類,匿名內部類。)
        Class<Object> objectClass = Object.class;
        // 接口
        Class<Comparable> comparableClass = Comparable.class;
        // 數組
        Class<String[]> stringClass = String[].class;
        Class<int[][]> intClass = int[][].class;
        // 枚舉
        Class<ElementType> elementTypeClass = ElementType.class;
        // 注解
        Class<Override> overrideClass = Override.class;
        // 基本數據類型
        Class<Integer> integerClass = Integer.class;
        // void
        Class<Void> voidClass = void.class;
        // Class
        Class<Class> classClass = Class.class;
    }
}

2.3 反射的使用

反射操作對象

public class UseClass {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class<User> userClass = User.class;

        /**
         * 通過構造器實例化對象:不使用構造器,默認通過無參構造進行對象創(chuàng)建
         */
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class, String.class);
        User user = declaredConstructor.newInstance("張三", "123456");
        System.out.println(user);

        /**
         * 調用方法并執(zhí)行相關操作
         */
        Method setUsername = userClass.getDeclaredMethod("setUsername", String.class);
        // invoke(Object, 參數):激活,即執(zhí)行相關操作為該對象
        setUsername.invoke(user, "李四");
        Method setPassword = userClass.getDeclaredMethod("setPassword", String.class);
        setPassword.invoke(user, "123456");
        System.out.println(user);

        /**
         * 操作屬性:通過反射直接操作私有屬性會報錯,需要通過setAccessible(ture)關閉訪問安全檢查,此方法屬性、方法和構造都具有,會影響效率
         */
        Field username = userClass.getDeclaredField("username");
        username.setAccessible(true);
        username.set(user, "用戶名");
        System.out.println(user);
    }
}

反射操作泛型

Java采用泛型擦除的機制來引入泛型,Java中的泛型僅僅是給編譯器javac使用的,確保數據的安全性和免去強制類型轉換問題。但是,一旦編譯完成,所有和泛型有關的類型全部擦除。

為了通過反射操作這些類型,Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType幾種類型來代表不能被歸一到Class類中的類型但是又和原始類型齊名的類型。

ParameterizedType:表示一種參數化類型,比如Collection

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

TypeVariable:是各種類型變量的公共父接口

WildcardType:代表一種通配符類型表達式

public class ClassOperateGenerics {
    public Map<String, String> list() {
        System.out.println("返回值是泛型");
        return new HashMap<>();
    }

    public void test(Map<String, User> map, List<Integer> list) {
        System.out.println("參數是泛型");
    }

    public static void main(String[] args) throws NoSuchMethodException {
        /**
         * 獲取方法參數的泛型
         */
        Method method = ClassOperateGenerics.class.getMethod("test", Map.class, List.class);
        // 獲取所有方法參數的泛型
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            // java.util.Map<java.lang.String, com.loner.mj.reflection.User>
            System.out.println(genericParameterType);
            if (genericParameterType instanceof ParameterizedType) {
                // 獲取所有泛型的真實參數
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    // String, User, Integer
                    System.out.println(actualTypeArgument);
                }
            }
        }

        /**
         * 獲取方法返回值的泛型
         */
        Method list = ClassOperateGenerics.class.getMethod("list", null);
        // 獲取方法返回值的泛型
        Type genericReturnType = list.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType) {
            // 獲取所有泛型的真實參數
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
    }
}

反射操作注解

public class ClassOperateAnnotation {
    public static void main(String[] args) throws NoSuchFieldException {
        Class<People> peopleClass = People.class;

        // 獲取類的所有注解
        Annotation[] declaredAnnotations = peopleClass.getDeclaredAnnotations();
        for (Annotation declaredAnnotation : declaredAnnotations) {
            System.out.println(declaredAnnotation);
        }
        // 獲取類的注解的值
        Table declaredAnnotation = peopleClass.getDeclaredAnnotation(Table.class);
        System.out.println(declaredAnnotation.value());

        // 獲取屬性的注解
        Field name = peopleClass.getDeclaredField("name");
        Fields annotation = name.getAnnotation(Fields.class);
        System.out.println(annotation.name());
    }
}

以上就是一文搞懂Java中的注解和反射的詳細內容,更多關于Java注解 反射的資料請關注腳本之家其它相關文章!

相關文章

  • springboot logback調整mybatis日志級別無效的解決

    springboot logback調整mybatis日志級別無效的解決

    這篇文章主要介紹了springboot logback調整mybatis日志級別無效的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • ElasticSearch查詢文檔基本操作實例

    ElasticSearch查詢文檔基本操作實例

    這篇文章主要為大家介紹了ElasticSearch查詢文檔基本操作實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • Spring Boot全局統(tǒng)一異常處理器

    Spring Boot全局統(tǒng)一異常處理器

    軟件開發(fā)springboot項目過程中,不僅有大量的冗余代碼,而且還影響代碼的可讀性.這樣就需要定義個全局統(tǒng)一異常處理器,以便業(yè)務層再也不必處理異常.文中有非常詳細的代碼示例,需要的朋友可以參考下
    2021-05-05
  • Mybatis3中方法返回生成的主鍵:XML,@SelectKey,@Options詳解

    Mybatis3中方法返回生成的主鍵:XML,@SelectKey,@Options詳解

    這篇文章主要介紹了Mybatis3中方法返回生成的主鍵:XML,@SelectKey,@Options,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • SpringBoot創(chuàng)建線程池的六種方式小結

    SpringBoot創(chuàng)建線程池的六種方式小結

    本文主要介紹了SpringBoot創(chuàng)建線程池的六種方式小結,包括自定義線程池,固定長度線程池,單一線程池,共享線程池,定時線程池,SpringBoot中注入異步線程池,感興趣的可以了解一下
    2023-11-11
  • Spring一步到位精通攔截器

    Spring一步到位精通攔截器

    攔截器(Interceptor)是一種動態(tài)攔截方法調用的機制,在SpringMVC中動態(tài)攔截控制器方法的執(zhí)行。本文將詳細講講SpringMVC中攔截器的概念及入門案例,感興趣的可以嘗試一下
    2023-01-01
  • SpringBoot整合log4j日志與HashMap的底層原理解析

    SpringBoot整合log4j日志與HashMap的底層原理解析

    這篇文章主要介紹了SpringBoot整合log4j日志與HashMap的底層原理,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • spring cloud gateway中redis一直打印重連日志問題及解決

    spring cloud gateway中redis一直打印重連日志問題及解決

    這篇文章主要介紹了spring cloud gateway中redis一直打印重連日志問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • kafka消費者kafka-console-consumer接收不到數據的解決

    kafka消費者kafka-console-consumer接收不到數據的解決

    這篇文章主要介紹了kafka消費者kafka-console-consumer接收不到數據的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 一個MIDP俄羅斯方塊游戲的設計和實現(xiàn)

    一個MIDP俄羅斯方塊游戲的設計和實現(xiàn)

    一個MIDP俄羅斯方塊游戲的設計和實現(xiàn)...
    2006-12-12

最新評論