Java之 注解

什么是注解

概念

An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated. Annotations have no direct effect on the operation of the code they annotate.

作用

Annotations have a number of uses, among them:
Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings.
Compile-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth.
Runtime processing — Some annotations are available to be examined at runtime.

  • 標(biāo)記,用于告訴編譯器一些信息

  • 編譯時動態(tài)處理,如動態(tài)生成代碼

  • 運行時動態(tài)處理,如得到注解信息

參考:
Java Annotation
Java Reflection - Annotations

注解的使用

格式

一個注解由一個@符號后面跟字符串組成,例如:

@Entity

java注解里面一般包含一些元素,這些元素類似于屬性或者參數(shù),可以用來設(shè)置值,比如我們有一個包含兩個元素的@Entity注解:

@Entity(name="mzw", job="碼農(nóng)")

該注解有兩個元素,name和job,分別賦予了元素值。

位置

注解可以用于描述一個類、接口、方法、方法參數(shù)、字段、局部變量等。

  • 方法:
@Override
public void mySuperMethod() { ... }

@SuppressWarnings(value = "unchecked")
public void myMethod() { ... }
@Author(
      name = "zphuan",
      date = "3/24/2017"
   )
public class MyClass() { ... }
  • 方法參數(shù)
pulic void myMethod(@RequestParam String s){ ... }
  • 局部變量
@Autowired
private MyClass myClass;

細(xì)節(jié)

  • 如果注解沒有參數(shù),則不用加參數(shù),如:@Override

  • 如果注解只有一個參數(shù),那么參數(shù)名字可以省略,如:

@SuppressWarnings("unchecked")
public void myMethod() { ... }
  • 一個地方可以使用多個注解,如:
@Author(name = "Jane Doe")
@EBook
public class MyClass { ... }
  • 可以重復(fù)使用注解,不過只有在java SE 8 才支持。比如:
@Author(name = "Jane Doe")
@Author(name = "John Smith")
public class MyClass { ... }

表明有兩個人對該類進行了代碼編寫。

內(nèi)置注解

java本身提供了三個內(nèi)置注解:

  • @Override
    注解是一個編譯時注解,它主要用在一個子類的方法中,當(dāng)被注解的子類的方法在父類中找不到與之匹配的方法時,編譯器會報錯。
  • @Deprecated
    可以用來描述一個類、方法或者字段,表示java不贊成使用這些被描述的對象,如果我們使用了這些類、方法或者字段,編譯器會給我們警告。
  • @SuppressWarnings
    作用是使編譯器忽略掉編譯器警告。比如,如果我們的一個方法調(diào)用了一個@Deprecated方法,或者做了一個不安全的類型轉(zhuǎn)換,此時編譯器會生成一個警告。如果我們不想看到這些警告,我們就可以使用@SuppressWarnings注解忽略掉這些警告。

自定義注解

元注解

元注解就是用來描述注解的注解,在java里面有下面幾個元注解:

  • @Documented
    作用是告訴JavaDoc工具,當(dāng)前注解本身也要顯示在Java Doc中。
  • @Retention
    用來定義注解的范圍,有下面三個范圍:
  1. RetentionPolicy.SOURCE
    注解只存在于源碼中,不會存在于.class文件中,在編譯時會被忽略掉。
  2. RetentionPolicy.CLASS
    注解只存在于.class文件中,在編譯期有效,但是在運行期會被忽略掉,這也是默認(rèn)范圍。
  3. RetentionPolicy.RUNTIME
    在運行期有效,JVM在運行期通過反射獲得注解信息。
  • @Target
    用于指定注解作用于java的哪些元素,未標(biāo)注則表示可修飾所有。

ElementType.ANNOTATION_TYPE ?Annotation type declaration
ElementType.CONSTRUCTOR ?Constructor declaration
ElementType.FIELD ?Field declaration (includes enum constants)
ElementType.LOCAL_VARIABLE ?Local variable declaration
ElementType.METHOD ?Method declaration
ElementType.PACKAGE ?Package declaration.
ElementType.PARAMETER ?Parameter declaration
ElementType.TYPE ?Class, interface (including annotation type), or enum declaration

  • @Inherited
    注解表示當(dāng)前注解會被注解類的子類繼承。

參考:
Java Doc

注解解析

運行時注解

首先,先定義一個注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {

    public String name();

    public String job();
}

上面通過元注解的定義,可以看出來自定義的注解是運行時注解,可以修飾所有的類型。

類注解
@MyAnnotation(name = "mzw", job = "給類添加了一個注解")
public class TestAnnotation { ... }

現(xiàn)在當(dāng)程序運行起來的時候我想要獲取到TestAnnotation中的@MyAnnotation的注解信息:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyAnnotation annotation = TestAnnotation.class.getAnnotation(MyAnnotation.class);
        Log.e("mzw", "name == " + annotation.name());
        Log.e("mzw", "value == " + annotation.value());
    }
}

運行后執(zhí)行結(jié)果為:

24603-24603/demo.remer.myannotation E/mzw: name == mzw
24603-24603/demo.remer.myannotation E/mzw: value == 給類添加了一個注解
方法注解
public class TestAnnotation {

    @MyAnnotation(name = "mzw", value = "給方法添加了一個注解")
    public void test(){

    }
}

當(dāng)程序運行時,可以獲取到類中test方法注解的信息:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            Class clazz = Class.forName(TestAnnotation.class.getName());
            for (Method method : clazz.getMethods()) {
                MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
                if (annotation != null) {
                    Log.e("mzw", "name === " + method.getName() + "||" + annotation.name());
                    Log.e("mzw", "value == " + method.getName() + "||" + annotation.value());
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

運行執(zhí)行的結(jié)果為:

20791-20791/demo.remer.myannotation E/mzw: name === test||mzw
20791-20791/demo.remer.myannotation E/mzw: value == test||給方法添加了一個注解
參數(shù)注解
public class TestAnnotation {

    public static void test(@MyAnnotation(name = "參數(shù)", value = "參數(shù)上的注解") String parameter){ ... }
}

運行程序,可以獲取到方法上的參數(shù)注解信息:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            Class clazz = Class.forName(TestAnnotation.class.getName());
            for (Method method : clazz.getMethods()) {
                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;
                            Log.e("mzw", "param === " + parameterType.getName());
                            Log.e("mzw", "name === " + myAnnotation.name());
                            Log.e("mzw", "value === " + myAnnotation.value());
                        }
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

運行執(zhí)行的結(jié)果為:

17392-17392/demo.remer.myannotation E/mzw: param === java.lang.String
17392-17392/demo.remer.myannotation E/mzw: name === 參數(shù)
17392-17392/demo.remer.myannotation E/mzw: value === 參數(shù)上的注解

注意
isAnnotationPresent(AnnotationName.class) 可以判斷Target是否被某個注解修飾

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 參考網(wǎng)址: 《秒懂,Java 注解 (Annotation)你可以這樣學(xué)》 《Java注解基本原理》 《注解A...
    琦小蝦閱讀 8,926評論 7 96
  • 內(nèi)容概要 Annotation的概念 Annotation的作用 Annotation的分類 系統(tǒng)內(nèi)置注解 元注解...
    DevinZhang閱讀 4,331評論 0 29
  • 1、Annotation的工作原理: JDK5.0中提供了注解的功能,允許開發(fā)者定義和使用自己的注解類型。該功能由...
    siriusF閱讀 307評論 0 0
  • 關(guān)于注解 定義:注解(Annotation),也叫元數(shù)據(jù)。一種代碼級別的說明。它是JDK1.5及以后版本引入的一個...
    mouekz閱讀 299評論 0 0
  • java自定義注解 Java注解是附加在代碼中的一些元信息,用于一些工具在編譯、運行時進行解析和使用,起到說明、配...
    尼爾君閱讀 560評論 0 0

友情鏈接更多精彩內(nèi)容