java基礎解析系列(六)---註解原理及使用

java基礎解析系列(六)---註解原理及使用

先來一個例子

class Father
{
    public void f()
    {}
}
public class Son extends Father{
    @Override
    public void f()
    {}
}
  • 當子類重寫父類的方法的時候,上面會出現一個 @Override ,這就是一個註解
@Controller
public class StudentController {
  • 框架中的@Controller也是一個註解

什麼是註解

public interface Annotation {
     boolean equals(Object obj);
     int hashCode();
     String toString();
     Class<? extends Annotation> annotationType();
}
  • 註解是一個接口
  • 從某方面看,註解的做用就像修飾符(public,final,static)同樣
  • 程序能夠經過反射來獲取指定程序元素的Annotion,而後經過Annotion來獲取註解裏面的元數據。

註解的種類

  • JDK內置系統註解
  • 元註解,用於'修飾'註解
  • 自定義註解

JDK內置系統註解

@Override

  • 上面的例子已經展現,這個註解的做用是用於修飾覆蓋了父類的方法

@Deprecated

  • 這個註解是用來修飾已通過時的方法

  • 能夠看到當方法用@Deprecated修飾,而後使用這個方法的時候,編譯器會提醒這個方法已通過時

@SuppressWarnnings

  • 用於忽略編譯器警告信息,告訴編譯器中止對此方法的警告。

元註解

@Target

  • 做用:被描述的註解能夠用在什麼地方
  • 參數值
ElementType 含義
ElementType 含義
ANNOTATION_TYPE 註解類型聲明
CONSTRUCTOR 構造方法聲明
FIELD 字段聲明(包括枚舉常量)
LOCAL_VARIABLE 局部變量聲明
METHOD 方法聲明
PACKAGE 包聲明
PARAMETER 參數聲明
TYPE 類、接口(包括註解類型)或枚舉聲明
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;


@Target(ElementType.FIELD)
public @interface MyAnnotation {

}
  • 上面是自定義的一個註解,用了一個@Target來修飾,代表這個自定義註解能夠用來修飾域

   

@Retention

  • 做用:指示註釋類型的註釋要保留多久
  • 參數值
RetentionPoicy 意義
SOURCE 源文件中保留,好比@Override,用於與編譯器交互
CLASS source,Class文件保留,用於編譯時生成額外的文件
RUNTIME sorce,class文件,運行時保留

@Documented

  • 做用:指示某一類型的註釋將經過 javadoc 和相似的默認工具進行文檔化
  • 被@Documented修飾的註解會生成到javadoc中
import java.lang.annotation.Documented;
@Documented
public @interface Demo
{

}
  • 打開cmd,而後執行javadoc Demo.java,而後能夠看到這個註解生成到了javadoc

@Inherited

  • 做用:指示註釋類型被自動繼承。可讓子類對象使用getAnnotations()獲取父類@Inherited修飾的註解。
@Inherited
@Retention( RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
    String msg() default "jiajun";
}



@MyAnnotation
class Father
{

}
class son extends Father{
    
}
    
public class Demo6
{
    public static void main(String[] args) {
        Father f=new son();
        System.out.println(Arrays.toString(f.getClass().getAnnotations()));
    }
}
//輸出:[@MyAnnotation(msg=jiajun)]

自定義註解

格式

  • public @interface 註解名 {定義體}

@Retention源碼

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
  • 能夠看到註解方法返回值是RetentionPolicy枚舉類型

使用

  • 用@interface(區別於interface)來聲明一個註解
  • 使用@interface定義註解的時候,自動繼承了Annotation接口
  • 用元註解修飾自定義註解
  • 定義體裏面能夠定義一些參數成員,default設置默認參數值
  • 使用註解的時候,傳值方式(msg=""),當參數名是value的時候,能夠直接用("666")的形式傳值。
  • 當沒有傳值的時候,@MyAnnotation(),獲取到的參數值是默認值

實驗

@Retention( RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
    String msg() default "jiajun";
}


@MyAnnotation(msg="666")
class Test1
{}
public class Test2 {
    
    public static void main(String[] args) {
        Test1 t=new Test1();
        Class c=t.getClass();
        MyAnnotation ma = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
        System.out.println(ma.msg());
    }
    
}
  • 自定義了一個MyAnnotation註解,用Retention註解聲明註解的生命週期,和Target修飾該註解的修飾範圍
  • Test1類用自定義的註解修飾,經過Class獲取相關信息。當Rention修飾的不是RUNTIME的時候,不能得到相關信息

訪問註解

訪問類註解

@Retention( RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
    String name() default "jiajun";
}
@MyAnnotation(name="jiajun")
public class Test {
}
public static void main(String[] args) {
        Class clazz = Test.class;
        Annotation[] annotations = clazz.getAnnotations();
        for(Annotation annotation : annotations){
            if(annotation instanceof MyAnnotation){
                MyAnnotation myAnnotation = (MyAnnotation) annotation;
                System.out.println("name: " + myAnnotation.name());
            }
        }
}

訪問方法註解

@Retention( RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    String name() default "jiajun";
}

public class Test {
    @MyAnnotation(name="jiajun")
    public void doSomething(){}
}


public class Demo {
    public static void main(String[] args) {
        Class clazz=Test.class;
        Method[]  methods=clazz.getMethods();
        for(Method method :methods)
        {
            if(method.getName()=="doSomething")
            {
                Annotation annotation = method.getAnnotation(MyAnnotation.class);
                if(annotation instanceof MyAnnotation){
                    MyAnnotation myAnnotation = (MyAnnotation) annotation;
                    System.out.println("name: " + myAnnotation.name());
                }
            }
        }
    }
}

訪問參數註解

@Retention( RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface MyAnnotation {
    String name() default "jiajun";
}
public class Test {
    public static void doSomething(
            @MyAnnotation(name="jiajun") String parameter){
    }
}
public class Demo {
    public static void main(String[] args) {
        Class clazz=Test.class;
        Method[]  methods=clazz.getMethods();
        for(Method method :methods)
        {
            if(method.getName()=="doSomething")
            {
                Annotation[][] parameterAnnotations = method.getParameterAnnotations();
                Class[] parameterTypes = method.getParameterTypes();

                int i=0;
                for(Annotation[] annotations : parameterAnnotations){
                    Class parameterType = parameterTypes[i++];

                    for(Annotation annotation : annotations){
                        if(annotation instanceof MyAnnotation){
                            MyAnnotation myAnnotation = (MyAnnotation) annotation;
                            System.out.println("param: " + parameterType.getName());
                            System.out.println("name : " + myAnnotation.name());
                        }
                    }
                }
            }
        }
    }
}
  • 每一個方法有n個參數,每一個參數包含一個註解數組,所以getParameterAnnotations()返回的是一個二維數組

我以爲分享是一種精神,分享是個人樂趣所在,不是說我以爲我講得必定是對的,我講得可能不少是不對的,可是我但願我講的東西是我人生的體驗和思考,是給不少人反思,也許給你一秒鐘、半秒鐘,哪怕說一句話有點道理,引起本身心裏的感觸,這就是我最大的價值。(這是我喜歡的一句話,也是我寫博客的初衷)

做者:jiajun 出處: http://www.cnblogs.com/-new/
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。若是以爲還有幫助的話,能夠點一下右下角的【推薦】,但願可以持續的爲你們帶來好的技術文章!想跟我一塊兒進步麼?那就【關注】我吧。html

相關文章
相關標籤/搜索