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.

  • 标记,用于告诉编译器一些信息

  • 编译时动态处理,如动态生成代码

  • 运行时动态处理,如得到注解信息

参考:
Java Annotation
Java Reflection - Annotations

注解的使用

格式

一个注解由一个@符号后面跟字符串组成,例如:

@Entity

java注解里面一般包含一些元素,这些元素类似于属性或者参数,可以用来设置值,比如我们有一个包含两个元素的@Entity注解:

@Entity(name="mzw", job="码农")

该注解有两个元素,name和job,分别赋予了元素值。

位置

注解可以用于描述一个类、接口、方法、方法参数、字段、局部变量等。

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

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

细节

  • 如果注解没有参数,则不用加参数,如:@Override

  • 如果注解只有一个参数,那么参数名字可以省略,如:

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

表明有两个人对该类进行了代码编写。

内置注解

java本身提供了三个内置注解:

  • @Override
    注解是一个编译时注解,它主要用在一个子类的方法中,当被注解的子类的方法在父类中找不到与之匹配的方法时,编译器会报错。
  • @Deprecated
    可以用来描述一个类、方法或者字段,表示java不赞成使用这些被描述的对象,如果我们使用了这些类、方法或者字段,编译器会给我们警告。
  • @SuppressWarnings
    作用是使编译器忽略掉编译器警告。比如,如果我们的一个方法调用了一个@Deprecated方法,或者做了一个不安全的类型转换,此时编译器会生成一个警告。如果我们不想看到这些警告,我们就可以使用@SuppressWarnings注解忽略掉这些警告。

自定义注解

元注解

元注解就是用来描述注解的注解,在java里面有下面几个元注解:

  • @Documented
    作用是告诉JavaDoc工具,当前注解本身也要显示在Java Doc中。
  • @Retention
    用来定义注解的范围,有下面三个范围:
  1. RetentionPolicy.SOURCE
    注解只存在于源码中,不会存在于.class文件中,在编译时会被忽略掉。
  2. RetentionPolicy.CLASS
    注解只存在于.class文件中,在编译期有效,但是在运行期会被忽略掉,这也是默认范围。
  3. RetentionPolicy.RUNTIME
    在运行期有效,JVM在运行期通过反射获得注解信息。
  • @Target
    用于指定注解作用于java的哪些元素,未标注则表示可修饰所有。

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
    注解表示当前注解会被注解类的子类继承。

参考:
Java Doc

注解解析

运行时注解

首先,先定义一个注解:

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

    public String name();

    public String job();
}

上面通过元注解的定义,可以看出来自定义的注解是运行时注解,可以修饰所有的类型。

类注解
@MyAnnotation(name = "mzw", job = "给类添加了一个注解")
public class TestAnnotation { ... }

现在当程序运行起来的时候我想要获取到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());
    }
}

运行后执行结果为:

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(){

    }
}

当程序运行时,可以获取到类中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();
        }
    }
}

运行执行的结果为:

20791-20791/demo.remer.myannotation E/mzw: name === test||mzw
20791-20791/demo.remer.myannotation E/mzw: value == test||给方法添加了一个注解
参数注解
public class TestAnnotation {

    public static void test(@MyAnnotation(name = "参数", value = "参数上的注解") String parameter){ ... }
}

运行程序,可以获取到方法上的参数注解信息:

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();
        }
    }
}

运行执行的结果为:

17392-17392/demo.remer.myannotation E/mzw: param === java.lang.String
17392-17392/demo.remer.myannotation E/mzw: name === 参数
17392-17392/demo.remer.myannotation E/mzw: value === 参数上的注解

注意
isAnnotationPresent(AnnotationName.class) 可以判断Target是否被某个注解修饰

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容

  • 参考网址: 《秒懂,Java 注解 (Annotation)你可以这样学》 《Java注解基本原理》 《注解A...
    琦小虾阅读 8,685评论 7 96
  • 内容概要 Annotation的概念 Annotation的作用 Annotation的分类 系统内置注解 元注解...
    DevinZhang阅读 4,169评论 0 28
  • 1、Annotation的工作原理: JDK5.0中提供了注解的功能,允许开发者定义和使用自己的注解类型。该功能由...
    siriusF阅读 238评论 0 0
  • 关于注解 定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个...
    mouekz阅读 275评论 0 0
  • java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配...
    尼尔君阅读 518评论 0 0