What is the Annotation?

时间:2022-09-05 19:39:17

Annotation称为注释或注解,它是一个接口。注解提供了一种为程序元素(类、方法、成员变量等)设置元数据(描述其它数据的数据)的方法。编译器、开发工具或其它程序中可以通过反射来获取程序中的Annotation对象,通过该对象获得注解里的元数据。注解不影响程序代码,通过使用注解可以在不改变程序逻辑的情况下,在源文件中嵌入一些补充信息。

1、基本注释

@Override:表明该方法是重写父类的方法,eg:

class Test
{
@Override
public void func()
{
......
}
}
  @Deprecated:表示该类或方法已过时,程序使用这些类或方法时会发出编译警告。

@SuppressWarnings:指示类或方法取消显示的编译警告,@SuppressWarnings中只有一个类型为String[]的元素成员value,其中常见的参数值为:

1.deprecation:使用了不赞成使用的类或方法时的警告;
   2.unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型; 
   3.fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;
   4.path:在类路径、源文件路径等中有不存在的路径时的警告; 
   5.serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告; 
   6.finally:任何 finally 子句不能正常完成时的警告; 
   7.all:关于以上所有情况的警告。

使用示例:

@SuppressWarnings(value="unchecked")
public void func1()
{
List list = new ArrayList<Integer>();
list.add(10); //list没有指定泛型,此处会产生警告

List<String> ls = list; //将不带泛型的对象赋给带泛型的对象,产生警告,导致“堆污染”
System.out.println(ls.get(0));//该语句运行时产生异常
}
@SuppressWarnings({"unchecked", "deprecation"})
public void func2()
{

}
   @SafeVarargs:指示取消显示个数可变形参产生的警告,eg:

@SafeVarargs
public static void func3(List<String>...aryStringList) //个数可变的形参相当于是数组,因为没有泛型数组,所以形参相当于是一个List[],泛型被抹去,产生“堆污染”
{

}
  @FunctionalInterface:指示该接口是一个函数式接口(只有一个抽象方法,可以包含多个默认方法或静态方法的接口)。

2、自定义注释

使用@interface来自定义一个注解,如下定义了名为Coder的注解,注解中包含两个元素personId(int类型)和company(String类型,默认值为"peking"):

public @interface Coder
{
int personId();
String city()default "peking";
}
  如果注释中仅包含一个元素,这个元素的名字应该为value,如:

public @interface Coder
{
String value();
}
  注释中可以包含枚举类型:

public @interface FruitColor 
{
public enum Color{ BULE,RED,GREEN}; //枚举
Color CoderColor() default Color.GREEN;
}
  声明(使用)自定义的注释的时候需要为其成员变量指定值,如果该变量无默认值的话:

@Coder(personId = 1001)
public void func()
{
......
}
  如果注释中元素的名字为value,那么在使用这个注解的时候,元素的名字和等号都可以省略,例如:

@Coder(“value”)
public void func()
{
......
}
  根据注解是否包含成员可以将注解分为标记注解(如@Override)和元注解(如@Retention)。

3、JDK的元注释

在java.lang.annotation下有6个元Annotation,其中@Repeatable用于定义重复注解,其余5个用来修饰自定义的注解。

@Retention:指定被修饰的Annotation保留的时间,通过指定其value成员变量的值:

//编译器把注释保存在class文件中,当运行java程序时,JVM不可获取注释信息,这是默认值。
@Retention(value = RetentionPolicy.CLASS)
@interface Testable{}

//编译器把注释保存在class文件中,当运行java程序时,JVM可以获取注释信息
//程序可以通过反射获取该注释
@Retention(value = RetentionPolicy.RUNTIME)
@interface Testable{}

//注释保存在源码中,编译器直接丢弃该注释。
@Retention(value = RetentionPolicy.SOURCE)
@interface Testable{}
  @Target:指定被修饰的Annotation能够修饰哪些程序单元,其成员value值常见的值有:

ElementType.TYPE为指定该Annotation可以修饰类、接口(包括注解)、枚举定义。
    ElementType.CONSTRUCTOR为指定该Annotation只能修饰构造方法。
    ElementType.METHOD为指定该Annotation只能修饰方法定义。
    ElementType.FIELD为指定该Annotation只能修饰成员变量。

@Documented:指定被修饰的Annotation将被javadoc工具提取成文档。

@Inherited:指定被修饰的Annotation具有继承性,使用该Annotation的类的子类自动继承该Annotation。

@Repeatable:在java 8之前,程序的元素(类、方法等)不能添加相同类型的注解,比如下面为使用两个@Result注解的实现方法:

@Results({@Result(name = "liyang"), @Result(name = "wulei")})
public void func()
{

}
    java 8中允许使用多个相同类型的注解,通过为注解添加@Repeatable修饰。

4、使用自定义的注解

可以为类中某些方法实现注解,然后其他程序通过使用实现反射功能的API来读取该注解,通过该注解或注解中的成员来做对应的一些处理:

//Foo.java

package xu;

import java.lang.annotation.*;

@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Testable
{
int id();
String city();
}

public class Foo
{
public static void main (String[] args)throws Exception
{

}
@Testable(id = 1001, city = "peking")
public static void func()
{
System.out.println("func called");
}
}
//Test.java

package xu;

import java.lang.annotation.*;
import java.lang.reflect.Method;

public class Test
{
public static void main (String[] args)throws Exception
{
//Class<?> cls = Class.forName("xu.Foo"); //获取类的class对象
//getMethod()获得类中指定方法,getMethods()获得类中所有方法。
for(Method m : Class.forName("xu.Foo").getMethods())
{
if(m.isAnnotationPresent(Testable.class)) //如果该方法使用了Testable注解
{
m.invoke(null); //调用该方法
}
}

//getAnnotation获得指定注解,getAnnotations获得所有注解
Annotation[] ary1 = Class.forName("xu.Foo").getMethod("func").getAnnotations();
for(Annotation tag : ary1)//输出Test类中func方法的所有注解
{
System.out.println(tag); 
}

//Foo tt = (Foo)cls.getDeclaredConstructor().newInstance(); //获取Foo类的实例
Foo tt = new Foo();
Annotation[] ary2 = tt.getClass().getMethod("func").getAnnotations();
for(Annotation tag : ary1)//获取tt对象的func方法的所有注解的元数据
{
if(tag instanceof Testable)
{
int id = ((Testable)tag).id();
String city = ((Testable)tag).city();
System.out.println(city + id);
}
}
}
}

/*
*/

5、类型注解

java 8中对@Target的成员value的值增加了ElementType.TYPE_USE,它被称作类型注解,指定被修饰的注解除了在定义程序元素(类、接口、方法、成员变量)时使用,还可以在任何用到类型的地方使用,如使用new创建对象、类型转换、使用implements实现接口、使用throws声明抛出异常的时候:

@Target(ElementType.TYPE_USE)
@interface notNull{}

@notNull
class Type implements @notNull Serializable 
{
public void func1()//throws @notNull FileNotFoundException
{
Object obj = "fkjava.org";
String str = (@NotNull String)obj;
Object win = new @NotNull JFrame("test");
}
public void func2(List<@NotNull String> info){}
}
6、APT

APT(Annotation Processing Tool)是一种注解处理工具,它能够提取出源文件中包含的注解信息,然后针对注解信息进行额外的处理。Annotation处理器通常会采用继承AbstractProcessor的方式来实现处理过程。javac命令中有一个-processor选项,它用来指定编译的时候使用指定的Annotation处理器提取并处理源文件中的注解。

What is the Annotation?的更多相关文章

  1. Spring Enable annotation – writing a custom Enable annotation

    原文地址:https://www.javacodegeeks.com/2015/04/spring-enable-annotation-writing-a-custom-enable-annotati ...

  2. 【java】细说 JAVA中 标注 注解(annotation)

    Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明.配置的功能.注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用 下面我们来详细说说这个注解,到底是怎么一 ...

  3. Java学习之注解Annotation实现原理

    前言: 最近学习了EventBus.BufferKinfe.GreenDao.Retrofit 等优秀开源框架,它们新版本无一另外的都使用到了注解的方式,我们使用在使用的时候也尝到不少好处,基于这种想 ...

  4. Java Annotation概述

    @(Java)[Annotation|Java] Java Annotation概述 用途 编译器的相关信息,如用于检测错误和一些警告 编译时和部署时的处理,如一些软件用于自动生成代码之类的 运行时处 ...

  5. hibernate学习三(使用Annotation,注解)

    一.新建一个工程hibernate_02_HelloWorld_Annotation(复制01工程并重命名); 二.新建一个实体类teacher.java,数据库中新建teacher表; import ...

  6. struts2使用annotation注意事项

    struts2使用annotation注意事项 1.包名只能以.action .actions  .struts  .struts2结尾.如:com.cnbolgs.web.actions 2.类名只 ...

  7. Data Validate 之 Data Annotation

    什么是Data Annotation ? 如何使用 ? 自定义Validate Attribute EF  Db first中使用Data Annotation asp.net MVC中使用Data ...

  8. SpringMvc的xml配置与annotation配置的例子的区别

    1.导入jar包时,要在xml配置基础上加 spring-aop-4.2.2.RELEASE.jar (注解的时候需要) 2.编写controller的时候要annotation需要做相关配置即红色部 ...

  9. spring3&period;0使用annotation完全代替XML&lpar;续&rpar;

    从回帖的反应来看,大多数人还是不赞成完全代替XML的,这点倒是在意料之中.我个人还是倾向于用代码来取代XML的Bean定义,当然这更多的是关乎个人偏好,不代表与我观点不同的人就是错的. 先来说说代码相 ...

  10. spring3&period;0使用annotation完全代替XML&lpar;三&rpar;

    很久之前写过两篇博客: spring3.0使用annotation完全代替XML spring3.0使用annotation完全代替XML(续) 用java config来代替XML,当时还遗留下一些 ...

随机推荐

  1. Canvas 最佳实践(性能篇)

    Canvas 想必前端同学们都不陌生,它是 HTML5 新增的「画布」元素,允许我们使用 JavaScript 来绘制图形.目前,所有的主流浏览器都支持 Canvas. Canvas 最常见的用途是渲 ...

  2. Shader实例&colon;一台旧电视

    准备: 1.一段小视频 2.一张电视机贴图 3.一张过滤图 效果: 让视频内容只在电视机屏幕区域显示 Shader代码:有注释 Shader "Joe/old_tv" { Prop ...

  3. GridView点击行触发SelectedIndexChanged事件

    1.在<% @Page ...... %>指令中添加 EnableEventValidation="false" 2.在RowDataBound事件中添加 protec ...

  4. Android中style的使用

    摘自搜搜问问. <item name="#1">#2</item> 1.item 的name属性#1可以为所有系统所带组件的属性,#2为此属性的值如andr ...

  5. &lbrack;wikioi&rsqb;石子归并

    http://wikioi.com/problem/1048/ 区间型动态规划.参考PPT:http://wenku.baidu.com/view/73c1ded5b9f3f90f76c61bc4.h ...

  6. javascriptDOM节点

    DOM把层次中的每一个对象都称之为节点(NODE),以HTML超文本标记语言为例:整个文档的一个根就是<html>,在DOM中可以使用 document.documentElement来访 ...

  7. 前后端分离djangorestframework——限流频率组件

    频率限制 什么是频率限制 目前我们开发的都是API接口,且是开房的API接口.传给前端来处理的,也就是说,只要有人拿到这个接口,任何人都可以通过这个API接口获取数据,那么像网络爬虫的,请求速度又快, ...

  8. KnockoutJs学习笔记(五)

    作为一名初学者来说,一篇篇的按顺序看官网上的文档的确是一件很痛苦的事情,毕竟它的排列也并非是由浅及深的排列,其中的顺序也颇耐人寻味,于是这篇文章我又跳过了Reference部分,进而进入到具体的bin ...

  9. crontab命令的使用方法

    crontab命令常见于Unix和Linux的操作系统之中,用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于"crontab"文件中,以供之后读取和执行. 在 ...

  10. The ECDSA host key for XXX has changed

    运行Hadoop时出现了: 导致运行失败.仔细分析后发现,这是因为以前192.168.1.201的主机名为master,后来把192.168.1.202改名为master,由于两台主机的公钥不一样,所 ...