首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 註解深度解析:元註解、自定義註解與反射解析實戰

     編輯:Java 綜合教學

Java 註解深度解析:從元註解到反射解析的完整指南

註解(Annotation)自 JDK 1.5 引入以來,已成為現代 Java 框架(Spring、Hibernate、MyBatis 等)的核心基礎設施。本文系統講解註解體系、元註解作用、自定義註解定義與反射解析實戰。

註解應用結構關係

三層調用鏈:註解定義 (A) → 業務類使用 (B) → 反射解析器 (C)

// A: 註解定義
@interface A { }

// B: 使用註解
@A class B { }

// C: 反射解析
class C {
    void parse() {
        if (B.class.isAnnotationPresent(A.class)) {
            A a = B.class.getAnnotation(A.class);
            // 讀取屬性值...
        }
    }
}

四大元註解詳解

元註解作用關鍵屬性/取值
@Retention 聲明註解生命週期 RetentionPolicy.SOURCE(源碼丟棄)、CLASS(默認,字節碼保留,VM 捨棄)、RUNTIME(運行期保留,可反射讀取)
@Target 限定註解適用程序元素 ElementType.TYPE(類/接口)、METHOD、FIELD、CONSTRUCTOR、PARAMETER、PACKAGE、LOCAL_VARIABLE 等
@Documented 標記註解納入 Javadoc 文檔 無屬性,標記即生效,類似 @see、@param
@Inherited 允許子類繼承父類註解 僅對 @Target(TYPE) 的註解生效

自定義註解語法規範

public @interface MyAnnotation {
    // 1. 參數聲明即方法,無參數、無拋出異常
    // 2. 返回類型限制:基本類型、String、Class、enum、Annotation、及其數組
    // 3. 可用 default 指定默認值

    String name();                    // 必填參數
    int id() default 0;               // 可選參數
    Class clazz();                 // Class 類型
    ElementType[] targets();          // 枚舉數組
    OtherAnnotation meta() default @OtherAnnotation; // 註解嵌套
}

完整實戰案例:三層結構演示

1. 定義註解 A.java

package com.example.annotation;

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface A {
    String name();
    int id() default 0;
    Class gid();
}

2. 業務類 B.java 多維度使用

package com.example.annotation;

import java.util.HashMap;
import java.util.Map;

@A(name = "type", gid = Long.class) // 類級註解
public class B {
    @A(name = "field", id = 1, gid = Long.class)
    private Integer age;

    @A(name = "constructor", id = 2, gid = Long.class)
    public B() {}

    @A(name = "publicMethod", id = 3, gid = Long.class)
    public void publicMethod() {}

    @A(name = "protectedMethod", id = 4, gid = Long.class)
    protected void protectedMethod() {
        Map m = new HashMap<>();
    }

    @A(name = "privateMethod", id = 5, gid = Long.class)
    private void privateMethod() {}
}

3. 反射解析器 C.java 全覆蓋解析

package com.example.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class AnnotationParser {

    /** 解析類級註解 */
    public static void parseTypeAnnotations(Class clazz) {
        for (Annotation ann : clazz.getAnnotations()) {
            if (ann instanceof A) {
                A a = (A) ann;
                System.out.printf("類註解: id=%d, name=%s, gid=%s%n", a.id(), a.name(), a.gid());
            }
        }
    }

    /** 解析方法級註解(含私有) */
    public static void parseMethodAnnotations(Class clazz) {
        for (Method method : clazz.getDeclaredMethods()) {
            if (method.isAnnotationPresent(A.class)) {
                A a = method.getAnnotation(A.class);
                System.out.printf("方法: %s, id=%d, name=%s, gid=%s%n",
                        method.getName(), a.id(), a.name(), a.gid());
            }
        }
    }

    /** 解析構造器註解 */
    public static void parseConstructorAnnotations(Class clazz) {
        for (Constructor ctor : clazz.getDeclaredConstructors()) {
            if (ctor.isAnnotationPresent(A.class)) {
                A a = ctor.getAnnotation(A.class);
                System.out.printf("構造器: %s, id=%d, name=%s, gid=%s%n",
                        ctor.getName(), a.id(), a.name(), a.gid());
            }
        }
    }

    public static void main(String[] args) {
        parseTypeAnnotations(B.class);
        parseMethodAnnotations(B.class);
        parseConstructorAnnotations(B.class);
    }
}

運行輸出示例

類註解: id=0, name=type, gid=class java.lang.Long
方法: publicMethod, id=3, name=publicMethod, gid=class java.lang.Long
方法: protectedMethod, id=4, name=protectedMethod, gid=class java.lang.Long
方法: privateMethod, id=5, name=privateMethod, gid=class java.lang.Long
構造器: com.example.annotation.B, id=2, name=constructor, gid=class java.lang.Long

最佳實踐建議

  • 運行期讀取必用 @Retention(RUNTIME),否則反射獲取不到
  • 精確限定 @Target,防止濫用於不支持的元素(如局部變量)
  • 善用 default,減少使用方樣板代碼
  • 註解嵌套:參數類型為另一註解類型,構建豐富元數據模型
  • 編譯期處理:結合 AnnotationProcessor 實現源碼生成、靜態檢查

註解是 Java 元編程的基石。掌握其定義規範、生命週期控制與反射解析技巧,是理解主流框架原理、開發基礎設施組件的必備技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved