第一节:注解(Annotation)的作用

Annotation(注解)是JDK5.0及以后版本引入的。它的作用是修饰程序元素。什么是程序元素呢?例如:包、类、构造方法、方法、成员变量等。

注解,就是对某一事物进行添加注释说明,会存放一些信息,这些信息可能对以后某个时段来说是很有用处的。

java提供了一套机制,使得我们可以对方法、类、参数、包、域以及变量等添加标注(即附上某些信息)。且在以后某个时段通过反射将标注的信息提取出来以供使用。

注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记。程序可以利用java的反射机制来了解你的类及各种元素上有无何种标记,针对不同的标记,就去做相应的事件。

第二节:定义注解

定义新的Annotation类型使用@interface关键字(在原有interface关键字前增加@符号)。定义一个新的Annotation类型与定义一个接口很像,例如:

public @interface Test{

}

定义完该Annotation后,就可以在程序中使用该Annotation。使用Annotation,非常类似于public、final这样的修饰符,通常,会把Annotation另放一行,并且放在所有修饰符之前。例如:

@Test

public class MyClass{

....

}

根据注解是否包含成员变量,可以把注解分为如下两类:标记注解:没有成员变量的Annotation被称为标记。这种Annotation仅用自身的存在与否来为我们提供信息,例如@override等。

元数据注解:包含成员变量的Annotation。因为它们可以接受更多的元数据,因此被称为元数据Annotation。 成员以无参数的方法的形式被声明,其方法名和返回值定义了该成员变量的名字和类型。

成员变量Annotation只有成员变量,没有方法。Annotation的成员变量在Annotation定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。例如:

public @interface MyTag{

string name();

int age();

}

示例中定义了2个成员变量,这2个成员变量以方法的形式来定义。

一旦在Annotation里定义了成员变量后,使用该Annotation时就应该为该Annotation的成员变量指定值。例如:

public class Test{

@MyTag(name="红薯",age=30)

public void info(){

......

}

}

也可以在定义Annotation的成员变量时,为其指定默认值,指定成员变量默认值使用default关键字。示例:

public @interface MyTag{

string name() default "我兰";

int age() default 18;

}

如果Annotation的成员变量已经指定了默认值,使用该Annotation时可以不为这些成员变量指定值,而是直接使用默认值。例如:

public class Test{

@MyTag

public void info(){

......

}

}

如果注解只有一个成员变量,则建议取名为value,在使用时可用忽略成员名和赋值符=

第三节:基本注解

在java.lang包下,JAVA提供了5个基本注解::

@Override

限定重写父类方法。对于子类中被@Override 修饰的方法,如果存在对应的被重写的父类方法,则正确;如果不存在,则报错。@Override 只能作用于方法,不能作用于其他程序元素。

@Deprecated

用于表示某个程序元素(类、方法等)已过时。如果使用了被@Deprecated修饰的类或方法等,编译器会发出警告。

@SuppressWarnings

抑制编译器警告。指示被@SuppressWarnings修饰的程序元素(以及该程序元素中的所有子元素,例如类以及该类中的方法.....)取消显示指定的编译器警告。例如,常见的@SuppressWarnings(value="unchecked")

SuppressWarnings注解的常见参数值的简单说明:

1.deprecation:使用了不赞成使用的类或方法时的警告(使用@Deprecated使得编译器产生的警告);

2.unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型; 关闭编译器警告

3.fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;

4.path:在类路径、源文件路径等中有不存在的路径时的警告;

5.serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告;

6.finally:任何 finally 子句不能正常完成时的警告;

7.all:关于以上所有情况的警告。

@SafeVarargs

@SafeVarargs是JDK 7 专门为抑制“堆污染”警告提供的。

@FunctionalIterface   (java 8 新增的)

函数式接口。Java8规定:如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法),该接口称为函数式接口。

@FunctionalInterface就是用来指定某个接口必须是函数式接口,否则就会编译出错。

@FunctionalInterface

public interface Fun

{

static void foo()

{

System.out.println("foo类方法");

}

default void bar()

{

System.out.println("bar默认方法");

}

void test();//只定义了一个抽象方法

}

如在上面的接口中再加一个抽象方法abc(),则会编译出错。

第四节 元注解

在java.lang.annotation包下,定义了6个元注解。元注解就是修饰注解的注解。

拿到一个注解,如何知道它是否是元注解呢?需要看它的元注解(无论是元注解还是普通注解都是有元注解的),如果看到这样的元注解:@Target(ElementType.ANNOTATION_TYPE),那么此时这个注解一定是元注解。

@Retention

@Target

@Documented

@Inherited

@Repeatable  (java 8新增)

类型注解

@Repetable和类型注解在另外一篇博文中介绍。

4.1 @Retention

@Retention用于指定注解可以保留多长时间(生命周期)。

@Retention包含一个名为“value”的成员变量,该value成员变量是RetentionPolicy枚举类型。使用@Retention时,必须为其value指定值。value成员变量的值只能是如下3个:

RetentionPolicy.SOURCE:Annotation只保留在源代码中,编译器编译时,直接丢弃这种Annotation,不记录在.class文件中。

RetentionPolicy.CLASS:编译器把Annotation记录在class文件中。当运行Java程序时,JVM中不可获取该Annotation信息。这是默认值

RetentionPolicy.RUNTIME:编译器把Annotation记录在class文件中。当运行Java程序时,JVM可获取该Annotation信息,程序可以通过反射获取该Annotation的信息。

示例:

package com.demo1;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

//name=value形式

//@Retention(value=RetentionPolicy.RUNTIME)

//直接指定

@Retention(RetentionPolicy.RUNTIME)

public @interface MyTag{

String name() default "我兰";

}

如果Annotation里有一个名为“value“的成员变量,使用该Annotation时,可以直接使用XXX(val)形式为value成员变量赋值,无须使用name=val形式。

4.2 @Target

@Target指定Annotation用于修饰哪些程序元素。@Target也包含一个名为”value“的成员变量,该value成员变量类型为ElementType[ ],ElementType为枚举类型,值有如下几个:

ElementType.TYPE:能修饰类、接口或枚举类型

ElementType.FIELD:能修饰成员变量

ElementType.METHOD:能修饰方法

ElementType.PARAMETER:能修饰参数

ElementType.CONSTRUCTOR:能修饰构造器

ElementType.LOCAL_VARIABLE:能修饰局部变量

ElementType.ANNOTATION_TYPE:能修饰注解

ElementType.PACKAGE:能修饰包

示例1(单个ElementType):

package com.demo1;

import java.lang.annotation.ElementType;

import java.lang.annotation.Target;

@Target(ElementType.FIELD)

public @interface AnnTest {

String name() default "sunchp";

}

示例2(多个ElementType):

package com.demo1;

import java.lang.annotation.ElementType;

import java.lang.annotation.Target;

@Target({ ElementType.FIELD, ElementType.METHOD })

public @interface AnnTest {

String name() default "sunchp";

}

4.3 @Documented

如果定义注解A时,使用了@Documented修饰定义,则在用javadoc命令生成API文档后,所有使用注解A修饰的程序元素,将会包含注解A的说明。

示例:

@Documented

public @interface Testable {

}

public class Test {

@Testable

public void info() {

}

}

4.4 @Inherited

@Inherited指定注解具有继承性。如果某个类使用了@xxx注解(定义该注解时使用了@Inherited修饰)修饰,则其子类将自动被@xxx修饰

示例:

package com.demo2;

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Inherited

public @interface MyTag{

}

package com.demo2;

@MyTag

public class Base {

}

package com.demo2;

//SubClass只是继承了Base类

//并未直接使用@MyTag注解修饰

public class SubClass extends Base {

public static void main(String[] args) {

System.out.println(SubClass.class.isAnnotationPresent(MyTag.class));

}

}

示例中Base使用@MyTag修饰,SubClass继承Base,而且没有直接使用@MyTag修饰,但是因为MyTag定义时,使用了@Inherited修饰,具有了继承性,所以运行结果为true。

如果MyTag注解没有被@Inherited修饰,则运行结果为:false。

第五节:注解的语法与定义形式

(1)以@interface关键字定义

(2)注解需要标明注解的生命周期,注解的修饰目标等信息,这些信息是通过元注解实现。

上面的语法不容易理解,下面通过例子来说明一下,这个例子就是Target注解的源码,

1

2

3

4

5

6

@Retention(value=RetentionPolicy.RUNTIME)

@Target(value={ElementType.ANNOTATION_TYPE})

public@interfaceTarget

{

ElementType[]value();

}

源码分析如下:

第一:元注解@Retention,成员value的值为RetentionPolicy.RUNTIME。

第二:元注解@Target,成员value是个数组,用{}形式赋值,值为ElementType.ANNOTATION_TYPE

第三:成员名称为value,类型为ElementType[]

另外,需要注意一下,如果成员名称是value,在赋值过程中可以简写。如果成员类型为数组,但是只赋值一个元素,则也可以简写。如上面的简写形式为:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

第六节:注解的底层实现

定义一个注解:

1

2

3

4

5

6

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

public@interfaceCache

{

Stringvalue()default"cache";

}

分析其字节码,如下图所示:

C:\Users\Administrator\workspace\cache\bin>javap -verbose Cache

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

Classfile/C:/Users/Administrator/workspace/cache/bin/Cache.class

Last modified2016-7-23;size429bytes

MD5checksum771f9c4d63ce2ded5d3b093deebd2c69

Compiled from"Cache.java"

publicinterfaceCacheextendsjava.lang.annotation.Annotation

minor version:0

majorversion:52

flags:ACC_PUBLIC,ACC_INTERFACE,ACC_ABSTRACT,ACC_ANNOTATION

Constantpool:

#1 = Class              #2             // Cache

#2 = Utf8               Cache

#3 = Class              #4             // java/lang/Object

#4 = Utf8               java/lang/Object

#5 = Class              #6             // java/lang/annotation/Annotation

#6 = Utf8               java/lang/annotation/Annotation

#7 = Utf8               value

#8 = Utf8               ()Ljava/lang/String;

#9 = Utf8               AnnotationDefault

#10 = Utf8               cache

#11 = Utf8               SourceFile

#12 = Utf8               Cache.java

#13 = Utf8               RuntimeVisibleAnnotations

#14 = Utf8               Ljava/lang/annotation/Retention;

#15 = Utf8               Ljava/lang/annotation/RetentionPolicy;

#16 = Utf8               RUNTIME

#17 = Utf8               Ljava/lang/annotation/Target;

#18 = Utf8               Ljava/lang/annotation/ElementType;

#19 = Utf8               TYPE

{

publicabstractjava.lang.Stringvalue();

descriptor:()Ljava/lang/String;

flags:ACC_PUBLIC,ACC_ABSTRACT

AnnotationDefault:

default_value:s#10

}

SourceFile:"Cache.java"

RuntimeVisibleAnnotations:

0:#14(#7=e#15.#16)

1:#17(#7=[e#18.#19])

分析上面的字节码,我们可以得出:

第一:

public interface Cache extends java.lang.annotation.Annotation,说明Cache注解是继承自Annotation,仍然是interface。

第二:

public abstract java.lang.String value(),说明value方法是abstract类型。

当开发者使用了注解修饰了类、方法、成员变量等成员之后,这些注解不会自己生效,必须由开发者提供相应的代码来提取并处理注解信息。这些提取和处理注解的代码统称为APT(Annotation Processing Tool)注解处理工具。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。这一部分在《Java自定义注解中讲解》 。

java path 注解_Java内置系统注解和元注解相关推荐

  1. java 表达式写法_java内置核心4大函数式接口写法和lambda表达式

    java.util.function , Java 内置核心四大函数式接口标准写发和lambda表达式 消费型接口,有一个输入参数,没有返回值 public static void main(Stri ...

  2. JDK注解(内置和自定义)

    JDK注解(内置和自定义) 1.内置 @Override:可以确保重写的方法,的确存在与父类.接口中,可以有效避免单词拼错的情况 @Deprecated:给用于提示,该方法由于安全,性能问题等,已经不 ...

  3. java 反射泛型方法_java基础之反射和泛型以及注解

    java基础之反射和泛型以及注解 泛型擦除 泛型擦除: 泛型只在编译时期有效,编译后的字节码文件中不存在泛型信息. 声明泛型集合,集合两端类型必须一致.类型也可以用包装类型,泛型的类型必须是引用类型, ...

  4. Android内置系统apk问题

    平台:Rockchip android版本: 7.1 个人博客:https://www.letcos.top/ 1.问题描述 ​ 一款产品需要内置定制的launcher,使用了一些第三方的sdk.按系 ...

  5. java对嵌入式_Java用于嵌入式系统的优点

    Java用于嵌入式系统的优点 与个人计算机这样的通用计算机系统不同,嵌入式系统通常执行的是带有特定要求的预先定义的任务.yjbys小编下面为你整理了关于Java用于嵌入式系统的优点,希望对你有所帮助. ...

  6. 企业级JAVA快速开发平台, 内置代码生成器 - JavaFast快速开发平台

    企业级JAVA快速开发平台, 内置代码生成器 - JavaFast快速开发平台 JavaFast是一款基于代码生成器的智能快速开发平台,可以帮助解决java项目中80%的重复工作,让开发者更多关注业务 ...

  7. JavaFast技术特点介绍-企业级JAVA快速开发平台, 内置java代码生成器

    企业级JAVA快速开发平台, 内置代码生成器 - JavaFast快速开发平台 JavaFast是一款基于代码生成器的智能快速开发平台,可以帮助解决java项目中80%的重复工作,让开发者更多关注业务 ...

  8. Windows内置系统账户Local system/Network service/Local Service

     内置系统账户:Local system/Network service/Local Service 区别 [ LocalSystem   账户] LocalSystem是预设的拥有本机所有权限的本地 ...

  9. 我的世界java版使用剑_我的世界:JAVA版藏“私货”内置绝世好剑与神功,你玩的版本有吗...

    导语:我的世界:JAVA版藏"私货"内置绝世好剑与神功,你玩的版本有吗! 在我的世界这款游戏中,每件物品都有它自己存在的作用,铁镐挖矿,盔甲防护,却也有一些物品被创作者赋予了奇怪的 ...

最新文章

  1. 《 嵌入式系统设计与实践》一一3.6 测试硬件(和软件)
  2. Apache Ignite——集合分布式缓存、计算、存储的分布式框架
  3. python帮助文档在哪_python文档在哪里
  4. IDEA :windows下Hadoop报错null\bin\winutils.exe
  5. 通过程序包管理器控制台解决版本错误(CS1705)
  6. Jackson Annotation Examples
  7. 推荐学习网页标准的20个好去处
  8. 在eclipse中搭建struts2框架的详细过程
  9. 进度管理工具 planner
  10. 网络流(最大流)基础入门
  11. 常见元件、封装及尺寸
  12. Go-Redis使用手册
  13. 生成扩散模型漫谈:DDPM = 自回归式VAE
  14. React Native 中使用图标
  15. 服务器win7无限重启,win7系统无限重启的解决方法
  16. DOS时代后,金山系再出神级办公软件,会像WPS一样普及
  17. keyshot渲染图文教程_keyshot基础图文教程,手把手教你用keyshot制作动画效果
  18. 【百元钱买百只鸡问题】一只公鸡5元钱,一只母鸡3元钱,三只小鸡1元钱。要求100元买100只鸡,请给出所有可行的结果?
  19. 图像传感器binning_CMOS图像传感器调试问题汇总
  20. weidl x DeepRec:热门微博推荐框架性能提升实战

热门文章

  1. wsdl和soap协议详细解析
  2. vivox21支持html,vivo X21支持快充吗_vivo X21支持无线充电吗-太平洋IT百科
  3. 2019宁夏计算机考试报名时间,2019年上半年宁夏计算机二级考试报名时间
  4. 在谷歌浏览器上面安装AxueRP插件。
  5. 【渝粤题库】广东开放大学 经济法实务 形成性考核
  6. 计算机平面设计教材,《计算机平面设计软件应用——全国中等职业技术学校计算机教材》低价购书_教材教辅考试_孔网...
  7. 室内设计师面试技巧有哪些?
  8. 计算机毕业设计django基于python企业资产管理系统
  9. 头牌知产介绍减肥药商标注册属于哪一类?
  10. 【计算机毕业设计】029网上购物商城系统