04. 掀開註解的神祕面紗

註解

1、註解的概念

註解:說明程序得,給計算機看的java

註釋:用文字描述程序,給程序員看的程序員

// 單行註釋
/* 多行註釋 */
/** 文檔註釋 */

註解的定義:api

​ 註解(Annotation),也叫元數據。一種代碼級別的說明。它是 JDK1.5 及之後版本引入的一個特性,與類、接口、枚舉是在同一個層次。它能夠聲明在包、類、字段、方法、局部變量、方法參數等的前面,用來對這些元素進行說明,註釋。數組

做用分類:ide

一、編寫文檔:經過代碼裏標識的註解生成文檔【生成文檔doc文檔】spa

二、編譯檢查:經過代碼裏標識的註解讓編譯器可以實現基本的編譯檢查【Override】code

三、代碼分析:經過代碼裏標識的註解對代碼進行分析【使用反射】對象

2、JDK 預約義註解

@Override 檢查方法是否繼承父類或接口繼承

@@Deprecated 該註解表示註釋的內容過期接口

@@SuppressWarnings 壓制警告

@SuppressWarnings("all")
public class AnnoDemo {
    @Override
    public String toString() {
        return "Demo01{}";
    }
    @Deprecated
    public void show(){
        //發現過期了,功能跟不上需求了
    }
    public void showNew(){
        //知足功能更增強大的方法
    }
    public void demo(){
        show(); //不推薦使用,但可使用
        showNew();
        Date date = new Date();
        date.getYear();//不推薦使用,但可使用
    }
}

3、自定義註解

格式

//元註解
public @interface MyAnno{
    //屬性列表
}

反編譯 javap AnnoName.class

public interface MyAnno extends java.lang.annotation.Annotation {

}

註解的本質其實就是一個接口,繼承Annotation父接口

/**
 * 註解的本質就是接口
 */
public @interface MyAnno {
    public String show();
}

屬性,在接口中定義的抽象方法

public @interface MyAnno {
    String Show1();
    int show2();
    String[] show3();
    AnnoName show4();
    PersonEnum show5();
}

1. 返回結果必須是以下類型

一、基本數據類型

二、String 類型

三、枚舉類型

四、註解

五、以上類型的數組

public @interface MyAnno {
    String show1();
    int show2();
    String[] show3();
    AnnoName show4();
    PersonEnum show5();
}

2. 屬性賦值需注意點

默認值

若是定義的屬性時,使用default關鍵字給屬性默認初始值,能夠在使用註解是不賦值

public @interface MyAnno {
    String name();
    int age() ;
}
public class Demo01 {
    @MyAnno(name="andy",age = 18)
    public void show(){
    }
}
public @interface MyAnno {
    String name();
    int age() default 18;
}
public class Demo {
    @MyAnno(name="andy")
    public void show(){
    }
}

value

若是隻有一個屬性須要賦值,並且該屬性的名稱是 value,那麼在賦值時 value能夠省略

public @interface MyAnno {
    String value();
}
public class Demo {
    @MyAnno("andy")
    public void show(){
    }
}

{}

數組賦值的時候,值使用 {} 包裹,若是數組中只有一個值,那麼{}能夠省略

public @interface MyAnno {
    String show1();
    String[] show2();//數組一個值的時候能夠省略大括號
    AnnoName show3();
    PersonEnum show4();
}
public class Demo01 {
    @MyAnno(show1="Andy",show3 = @AnnoName,show4 = PersonEnum.P1,show2 = {"a","b"})
    public void show(){
    }
}

4、元註解

JDK 中給咱們提供的4個元註解

1. @Target

描述當前註解可以做用的位置

​ 一、ElementType.TYPE,能夠做用在類上

​ 二、ElementType.METHOD,能夠做用在方法上

​ 三、ElementType.FIELD,能夠做用在成員變量上

@Target({ElementType.TYPE, ElementType.METHOD,ElementType.FIELD})
public @interface MyAnno {

}
@MyAnno
public class Worker {
    @MyAnno
    private String name;
    @MyAnno
    public void show(){
    }
}

2. @Retention

描述註解被保留到的階段

SOURCE < CLASS < RUNTIME

​ 一、SOURCE,表示當前註解只在代碼階段有效

​ 二、CLASS,表示該註解會被保留到字節碼階段

​ 三、RUNTIME,表示該註解會被保留到運行階段 JVM

//自定義的註解,通常用RUNTIME
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {

}

3. @Documented

描述註解是否被抽取到 JavaDoc api中

4. @@Inherited

描述註解是否能夠被子類繼承

5、自定義註解案例

public class Teacher {
    public void show(){
        System.out.println("Teacher show ....");
    }
}
public class Student {
    public void show(){
        System.out.println("student show ....");
    }
}
/**
 * 自定義註解
 *  該註解標明要執行哪一個類中哪一個方法
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InvokAnno {
    String className();
    String methodName();
}
@InvokAnno(className = "com.andy.anno.Student",methodName = "show")
public class MyMain {
    public static void main(String[] args) throws Exception {
        //獲取類對象
        Class<MyMain> clazz = MyMain.class;
        //獲取類對象中的註解
        InvokAnno annotation = clazz.getAnnotation(InvokAnno.class);
        /*
        註解本質是 接口 獲取到的其實時接口的實現
        public class MyInvokAnno implements InvokAnno{
            String className(){
                return "com.andy.anno.student";
            }
            String methodName(){
                return "show";
            }
        }
         */
        //獲取註解中對應的屬性
        String className = annotation.className();
        String methodName = annotation.methodName();
        System.out.println(className+" "+methodName);
        //經過反射的方式實現接口的功能
        Class<?> aClass = Class.forName(className);
        Method show = aClass.getDeclaredMethod("show");
        Object o = aClass.newInstance();
        show.invoke(o);
    }
}
相關文章
相關標籤/搜索