Java的自定義注解使用實例


概念

Java有五個元注解,自動繼承java.lang.annotation.Annotation。

什么是元注解,可以理解為其他普通注解進行解釋說明

@Target  該注解的使用范圍,限定應用場景。枚舉類 ElemenetType 中

  1. TYPE:類,接口
  2. FIELD:字段,枚舉的常量
  3. METHOD:函數(方法)
  4. PARAMETER:參數
  5. CONSTRUCTOR:構造函數
  6. ANNOTATION_TYPE:注解類型
  7. LOCAL_VARIABLE:局部變量
  8. PACKAGE:包

@Retention  該注解的生存周期,相當於時間戳。枚舉類型 RetentionPolicy 中

  1. SOURCE:在源文件中有效,編譯后會被丟棄(如@Override,@Deprecated)
  2. CLASS:在class文件中有效,在jvm丟棄
  3. RUNTIME:在運行時有效,class文件保留,jvm運行時保留(很多框架運用反射調用)

@Documented

javadoc文檔生成工具的使用

@Inherited

允許子類繼承父類中的注解。

@Repeatable

同一種注解可多次使用

作用

  1. 注釋,解釋,通過代碼的標識元數據生成doc文檔;
  2. 使用反射,通過代碼標識的元數據對代碼進行分析;
  3. 編譯檢查,通過代碼標識的元數據讓編譯器進行基本檢查。

實例

定義一個普通的注解,

public @interface Test
{

}

使用我們自定義的注解

@Test
public class Person
{
    @Test
    private String name;

    @Test
    private int age;

    @Test
    public void say()
    {
        System.out.println("Hello,Java Annotation");
    }
}

@Target(ElementType.PACKAGE) 注解作用的目標>包

這個注解要理解什么是友好聲明類和包常量,包中有很多的內部訪問的類或常量,就可以統一的放到友好聲明類中,這樣就方便,而且集中管理,減少friendly類到處游走的情況。

可以參考這個 https://www.cnblogs.com/DreamDrive/p/5428573.html

import java.lang.annotation.ElementType;
@Target(ElementType.PACKAGE)
public @interface Test
{
}
@Test
package test;

class Person
{

    private String name;


    private int age;


    public void say()
    {
        System.out.println("Hello,Java Annotation");
    }
}

@Target(ElementType.CONSTRUCTOR) 注解作用的目標>構造函數

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.CONSTRUCTOR)
public @interface Test
{

}
package test;

public class Person
{

    private String name;

    private int age;
    @Test
    public Person()
    {

    }

    public void say()
    {
        System.out.println("Hello,Java Annotation");
    }
}

其他范圍就不一一列舉,都是相同的。

@Retention(RetentionPolicy.RUNTIME)   生存周期

代碼運行時動態獲取注解的信息

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.CONSTRUCTOR)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test
{

}
package test;

public class Person
{

    private String name;

    private int age;
@Test
public Person() { } public void say() { System.out.println("Hello,Java Annotation"); } }

 注解的屬性-->成員變量

方法名是成員變量的的名字,變量的類型是他的返回值。

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) 
public @interface Test
{
    public int age() default 20;

    public String name() default "";

    public String className();
}
package test;

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

@Test(age = 15,name = "zhangsan",className = "高三(3)班")
public class Person
{
 
    private String name;

    private int age;

    public Person()
    {

    }

  
    private void say()
    {
        System.out.println("Hello,Java Annotation");
    }
}

既然給了注解,我們要做的工作必然是要提取注解上面的內容,要拿到這些注解就要用到反射。

package test;

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

@Test(age = 15,name = "zhangsan",className = "高三(3)班")
public class Person
{private String name;
    
    private int age;

    public Person()
    {

    }
    
    private void say()
    {
        System.out.println("Hello,Java Annotation");
    }

    public static void main(String[] args)
    {
        boolean hasAnnotation = Person.class.isAnnotationPresent(Test.class);

        if (hasAnnotation)
        {
            Test test = Person.class.getAnnotation(Test.class);

            System.out.println("age:" + test.age());
            System.out.println("name:" + test.name());
            System.out.println("className:" + test.className());
        }
}
}

輸出結果

age:15
name:zhangsan
className:高三(3)班

對於類的屬性和方法,都是同樣的道理。

成員注解

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Field
{
    public String name();
}

函數注解

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Method
{
    public String say();
}

Person類

package test;

import java.lang.annotation.Annotation;

@Test(age = 15,name = "zhangsan",className = "高三(3)班")
public class Person
{
    @Field(name = "lisi")
    private String name;

    private int age;

    public Person()
    {

    }
    @Method(say = "hello")
    private void say()
    {
        System.out.println("Hello,Java Annotation");
    }

    public static void main(String[] args)
    {
        boolean hasAnnotation = Person.class.isAnnotationPresent(Test.class);

        if (hasAnnotation)
        {
            Test test = Person.class.getAnnotation(Test.class);

            System.out.println("age:" + test.age());
            System.out.println("name:" + test.name());
            System.out.println("className:" + test.className());
        }

        try
        {
            java.lang.reflect.Field field = Person.class.getDeclaredField("name");

            field.setAccessible(true);

            Field check = field.getAnnotation(Field.class);

            if (check != null)
            {
                System.out.println("check value:" + check.name());
            }

            java.lang.reflect.Method method = Person.class.getDeclaredMethod("say");  

            if (method != null)
            {
                Annotation[] ans = method.getAnnotations();
                for (int i = 0; i < ans.length; i++)
                {
                    System.out.println("method annotation:" + ans[i].annotationType().getSimpleName());
                }
             }

        } catch (NoSuchFieldException e)
        {
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

輸出

age:15
name:zhangsan
className:高三(3)班
check value:lisi
method annotation:Method

可以看出我們獲取了注解上的值,現在都沒有實際意義,我們可以用注解來做些什么?

這些我沒辦法給出確切答案,只能說根據各人需求去合理利用注解。

實例

注解參數賦值

@Test注解

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Test
{
    String value();
}

Person類屬性賦值

package test;

import org.apache.poi.ss.formula.functions.T;

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

public class Person
{
    @Test("zhangsan")
    private String name;

    @Test("15")
    private int age;

    public Person()
    {

    }

    private void say()
    {
        System.out.println("Hello,Java Annotation");
    }

    @Override
    public String toString()
    {
        return "name = " + name + "\n" + "age = " + age;
    }

    public static void main(String[] args)
    {
        Person person = new Person();
        try
        {
            //取得成員變量的值
            Field field = Person.class.getDeclaredField("name");
            //打開權限
            field.setAccessible(true);
            //判斷屬性是否有注解
            if (field.isAnnotationPresent(Test.class))
            {
                //獲取屬性上的注解值
                Test test = field.getAnnotation(Test.class);
                String name = test.value();
                //賦值
                field.set(person,name);
            }

            Field field1 = Person.class.getDeclaredField("age");
            field1.setAccessible(true);
            if (field1.isAnnotationPresent(Test.class))
            {
                Test test = field1.getAnnotation(Test.class);
                int age = Integer.valueOf(test.value());
                field1.set(person,age);
            }
            System.out.println(person);

        }catch (Exception e)
        {
            e.printStackTrace();
        }

    }
}

輸出

name = zhangsan
age = 15

用注解去檢查函數等等。。

lz不善於用語言表達,所以可能有很多人沒看懂,可以看下

一個大佬講解的注解說明(簡單易懂)

 https://blog.csdn.net/briblue/article/details/73824058


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM