澳门新浦京娱乐游戏Java 注解全面解析

1.基本语法

讲授定义看起来很像接口的概念。事实上,与任何任何接口同样,注脚也将会编写翻译成class文件。

@Target(ElementType.Method)

@Retention(RetentionPolicy.RUNTIME)

public @interface Test {}

除了@符号以外,@Test的定义很像三个空的接口。定义注脚时,需求部分元申明(meta-annotation),如@Target和@Retention

@Target用来定义声明将接受于怎么样地点(如叁个方法照旧三个域)

@Retention用来定义注脚在哪叁个等级可用,在源代码中(source),类公事中(class)可能运营时(runtime)

在批注中,日常都会含有部分要素以代表有个别值。当解析管理申明时,程序能够使用这一个值。未有成分的讲授称为标志注明(marker
annotation)

各类元表明,元申明专职担当阐明别的的诠释,所以那多种申明的Target值都是ElementType.ANNOTATION_TYPE

注解 说明
@Target 表示该注解可以用在什么地方,由ElementType枚举定义
CONSTRUCTOR:构造器的声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明
ANNOTATION_TYPE:注解声明(应用于另一个注解上)
TYPE_PARAMETER:类型参数声明(1.8新加入)
TYPE_USE:类型使用声明(1.8新加入)
PS:当注解未指定Target值时,此注解可以使用任何元素之上,就是上面的类型
@Retention 表示需要在什么级别保存该注解信息,由RetentionPolicy枚举定义
SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
CLASS:注解在class文件中可用,但会被VM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机(JVM)中)
RUNTIME:VM将在运行期也保留注解信息,因此可以通过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息)
PS:当注解未定义Retention值时,默认值是CLASS
@Documented 表示注解会被包含在javaapi文档中
@Inherited 允许子类继承父类的注解

怎么是评释

  • 注脚能够看作类的第6大因素(成员变量、结构器、方法、代码块、内部类)
  • 注明有一点像修饰符,可以修饰一些程序要素:类、接口、变量、方法、局地变量等等
  • 疏解要和对应的配套工具(APT:Annotation Processing
    Tool卡塔尔一同使用,APT会对含有表明实香港行政局地甩卖
  • 举个例子API文书档案里面,某些措施上面的“@Deprecated”,正是三个注脚,它意味着那个主意已经过时,使用的时候会摄取警告
  • 表明完全不影响程序的功能

2. 疏解元素

– 注解元素可用的品种如下:

– 全部骨干项目(int,float,boolean,byte,double,char,long,short)

– String

– Class

– enum

澳门新浦京娱乐游戏,– Annotation

– 以上项目标数组

一旦接收了别样体系,那编写翻译器就能够报错。也不容许行使任何包装档期的顺序。注明也足以视作成分的连串,也正是表明能够嵌套。

要素的修饰符,只可以用public或default。

– 默许值节制

编写翻译器对成分的暗中同意值某个过分责问。首先,成分不能够有不明确的值。也正是说,成分必须要么具备默许值,要么在接收注解时提供要素的值。

附带,对于非主导项指标要素,无论是在源代码中表明,依然在疏解接口中定义私下认可值,都不能够以null作为值。那便是限量,那就招致微处理机很难显现七个要素的存在或缺点和失误状态,因为各样注脚的注解中,全数的元素都存在,並且都统筹相应的值。为了绕开这么些范围,只好定义一些差别常常的值,举个例子空字符串或负数,表示有个别成分不设有。

@Target(ElementType.Method)

@Retention(RetentionPolicy.RUNTIME)

public @interface MockNull {

public int id() default -1;

public String description() default “”;

}

元注解

  • 元注脚有6个,坐落于java.lang.annotation包下
  • @Retention
    • 不能不修饰注解
    • 用以钦命被修饰的注释,能够保存到如何日子
    • @Retention唯有二个因素:value,是RetentionPolicy类型,那是个枚举类,只犹如下多个值
      • RetentionPolicy.SOURCE:评释只保留在源代码中,编写翻译阶段即被吐弃
      • RetentionPolicy.CLASS:保留在class文件中,程序运维时,JVM不能够取获得该注脚
      • RetentionPolicy.RUNTIME:保留在class文件中,程序运维时,能够通过反射取得该注明
  • @Target
    • 唯其如此修饰注解
    • 用以钦命被修饰的批注,能够用来修饰哪些程序成分
    • @Target唯有多少个因素:value,是ElementType[]项目,ElementType也是个枚举类,只犹如下拾个值
      • ElementType.TYPE:表示被修饰的注脚能够修饰类、接口、注明、枚举
      • ElementType.FIELD:只可以修饰成员变量
      • ElementType.METHOD:只可以修饰方法
      • ElementType.PARAMETE安德拉:能够修饰参数
      • ElementType.CONSTRUCTO安德拉:只好修饰布局器
      • ElementType.LOCAL_VALX570IBLE:只可以修饰局地变量
      • ElementType.ANNOTATION_TYPE:只可以修饰注脚
      • ElementType.PACKAGE:只可以修饰包
      • ElementType.TYPE_USE:since
        1.8,表示声明能写在使用类型变量的语句中
      • ElementType.TYPE_PARAMETE冠道:since
        1.8,表示证明能写在项目变量的声明语句中
  • @Documented
    • 修饰注明,该申明将被javadoc提取步入文书档案
    • 该元申明未有成分
  • @Inherited
    • 修饰注脚,表示该表明具有世襲性
    • 诸如:三个父类使用了一个表明X修饰,而X申明在概念时用了@Inherited修饰,那么子类自动被X修饰
  • @Repeatable
    • 用以修饰四个解说,表示该注明能够用来重复注明
    • 含蓄一个变量value,是Annotation的Class类型
  • @Native

3. 急迅格局

何为快捷方式呢?先来看下springMVC中的Controller注脚

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Component

public @interface Controller {

String value() default “”;

}

能够望见Target应用于类、接口、注脚和枚举上,Retention攻略为RUNTIME运营时期,有一个String类型的value成分。平时使用的时候基本都以如此的:

@Controller(“/your/path”)

public class MockController { }

那正是火速情势,省略了名-值没错这种语法。上面给出详细表达:

注明中定义了名叫value的成分,而且在使用该注解的时候,假诺该因素是有一无二供给赋值的三个要素,那么那时无需接纳名-值对的这种语法,而只需在括号内交付value元素所需的值就能够。那能够运用于此外官方类型的要素,当然了,那节制了成分名必需为value。

中央声明

  • 主干申明有5个,坐落于java.lang包下
  • @Override
    • 只能修饰方法;保留在源代码阶段
    • 告知编写翻译器,被该修饰符修饰的不二秘籍是在重写父类的不二秘诀,假如父类中并未有同样具名的形式,那么会发出错误
  • @Deprecated
    • 修饰布局器、成员变量、局地变量、方法、包、参数、类、注释、枚举;保留到运维阶段;javadoc提取
    • 表示该因素已不适当时候宜,别的地方接受那些要素时,编写翻译器会交到警示
  • @SuppressWarnings
    • 修饰类、接口、注脚、枚举、成员变量、方法、参数、布局方法、局地变量;保留在源代码阶段;
    • 独有一个变量value,类型为String[]
    • 被修饰的主次成分及子成分撤消value钦命的编写翻译器警示
  • @SafeVarargs
    • 修饰布局器、方法;保留在运营阶段;javadoc提取
    • 非常修饰会掀起“堆污染”警示的主意仍旧布局器
    • since 1.7
  • @FunctionalInterface
    • 只好修饰接口;保留到运维阶段;javadoc提取
    • 告诉编写翻译器严谨检查,该接口为函数式接口
    • since 1.8

4. JDK1.8注脚加强

TYPE_PARAMETER和TYPE_USE

在JDK1.第88中学ElementType多了八个枚举成员,TYPE_PARAMETER和TYPE_USE,他们都以用来界定哪个品种能够开展表明。比释尊讲,若是想要对泛型的连串参数进行表明:

public class AnnotationTypeParameter<@TestTypeParam T> {}

那么,在定义@TestTypeParam时,必须在@Target设置ElementType.TYPE_PARAMETEGL450,表示这几个注明能够用来标记类型参数。比如:

@Target(ElementType.TYPE_PARAMETER)

@Retention(RetentionPolicy.RUNTIME)

public @interface TestTypeParam {}

ElementType.TYPE_USE用于注解各连串型,因而地方的例证也足以将TYPE_PARAMETER改为TYPE_USE,四个讲明被安装为TYPE_USE,只假若项目名称,都能够张开疏解。举例有如投注明定义:

@Target(ElementType.TYPE_USE)

@Retention(RetentionPolicy.RUNTIME)

public @interface Test {}

那么以下的使用注解都以足以的:

List<@Test Comparable> list1 = new ArrayList<>();

List<? extends Comparable> list2 = new ArrayList<@Test
Comparable>();

@Test String text;

text = (@Test String)new Object();

java.util. @Test Scanner console;

console = new java.util.@Test Scanner(System.in);

PS:以上@Test评释都以在品种的左侧,要留意区分1.8事情未发生前的枚举成员,举个例子:

@Test java.lang.String text;

在上头这么些事例中,显明是在进展text变量表明,所以还动用当前的@Target会编写翻译错误,应该加上ElementType.LOCAL_VARIABLE。

@Repeatable注解

@Repeatable证明是JDK1.8新到场的,从名字意思就足以大致猜出她的乐趣(可重复的)。能够在同三个职位再次形似的注释。比如:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface Filter {

String [] value();

}

如下实行解说使用:

@Filter({“/admin”,”/main”})

public class MainFilter { }

换一种风格:

@Filter(“/admin”)

@Filter(“/main”)

public class MainFilter {}

在JDK1.8还未现身在此之前,没有艺术到达这种“风格”,使用1.8,能够如下概念@Filter:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Repeatable(Filters.class)

public @interface Filter {

String  value();

}

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface Filters {

Filter [] value();

}

实在此是编写翻译器的优化,使用@Repeatable时告诉编写翻译器,使用@Filters来作为搜聚重复评释的容器,而各种@Filter存款和储蓄各自钦赐的字符串值。

JDK1.8在AnnotatedElement接口新添了getDeclaredAnnotationsByType和getAnnotationsByType,在钦赐@Repeatable的讲授时,会招来重复注解的器皿中。相对于,getDeclaredAnnotation和getAnnotation就不会管理@Repeatable注脚。比如如下:

@Filter(“/admin”)

@Filter(“/filter”)

public class FilterClass {

public static void main(String[] args) {

Class<FilterClass> filterClassClass = FilterClass.class;

Filter[] annotationsByType =
filterClassClass.getAnnotationsByType(Filter.class);

if (annotationsByType != null) {

for (Filter filter : annotationsByType) {

System.out.println(filter.value());

}

}

System.out.println(filterClassClass.getAnnotation(Filter.class));

}

}

日记如下:

/admin

/filter

null

自定义注明

  • 自定义注脚跟定义接口雷同,只是用“@interface”关键字替换“interface”
  • 能够用某些元表明修饰就能够,对于保存时间,假若不写@Target,那么默许是修饰任何程序要素
  • 能够包涵变量
  • 比方说@Deprecated的源代码是如此的

    package java.lang;

    import java.lang.annotation.;
    import static java.lang.annotation.ElementType.
    ;

    @Documented //元评释:表示该注明会被javadoc提取到文书档案中
    @Retention(RetentionPolicy.RUNTIME卡塔尔 //元评释:保留到运营阶段
    @Target(value={CONSTRUCTO大切诺基, FIELD, LOCAL_VA陆风X8IABLE, METHOD, PACKAGE, PARAMETE传祺, TYPE}卡塔尔(قطر‎ //元申明:能够修饰的前后相继成分public @interface Deprecated {
    }

  • 再比方@SuppressWarnings的源代码

    package java.lang;

    import java.lang.annotation.;
    import static java.lang.annotation.ElementType.
    ;

    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuppressWarnings {

    String[] value();                       //可以包含变量,String[]是该变量的类型
    

    }

  • 包罗变量的时候,使用时就不可能只写表明名称,还得写变量的值,比方:

    @SuppressWarnings(value=”unchecked”State of Qatar//假使独有四个变量,那么能够回顾变量名:
    @SuppressWarnings(“unchecked”卡塔尔国

  • 不写变量名和值,那么该证明在概念的时候,就得定义暗中认可值,用default关键字,举个例子

    @Target({TYPE, FIELD}卡塔尔(قطر‎ //独有多少个变量,省略变量名
    @Retention(RetentionPolicy.CLASS卡塔尔 //独有一个变量,省略变量名
    public @interface Test{

    String name() default "Java";        //用default指定默认值
    int age() default 18;                //用default指定默认值
    

    }

  • 实则,自定义申明暗中认可都以再而三了java.lang.annotation.Annotation接口的,见示例:

    package testpack;
    public class Test1 {

    public static void main(String[] args){ 
        Class clazz=Test.class;
        Class[] is=clazz.getInterfaces();
        for (Class i:is) {
            System.out.println(i);    //输出:interface java.lang.annotation.Annotation
        }
    }
    

    }
    @interface Test{

    }

讲授的分类

  • 标识注明:不含有成员变量
  • 元数据注脚:满含成员变量

收获程序成分的笺注音讯

  • 光有评释没用,还得有对应的工具来管理,要管理,得先拿走申明新闻
  • 取获得注明音讯的前提是,声明能保留到”获取”这些操作的时候
  • 在文章0033
    Java学习笔记-反射-开始1中涉嫌,通过反射能够得到二个类的笺注音信,有四个点子,其实那一个主意都来源于于一个接口:java.lang.reflect.AnnotatedElement,Class是它的兑现类之一
  • java.lang.reflect.AnnotatedElement是个接口,表示程序中得以担任申明的顺序成分,首要犹如下多少个实现类
    • Package
    • Class
    • Filed
    • Constructor
    • Method
    • Parameter
  • 以上那么些类都满含0033
    Java学习笔记-反射-初阶1中有关获取申明的那6个方法,
  • 除上述6个点子外,还大概有一个艺术用于剖断程序成分上是还是不是留存指定项目标笺注:boolean
    isAnnotationPresent(Class<? extends Annotation>
    annotationClassState of Qatar
  • 见示例:

    package testpack;

    import java.lang.annotation.Annotation;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;

    @Test(name=”Java”,age=18)
    public class Test1 {

    public static void main(String[] args){ 
        Class clazz=Test1.class;
        Annotation a=clazz.getAnnotation(Test.class);    //获取对应类的Test类型的注解
        System.out.println(a);
        if (a instanceof Test){
            System.out.println(((Test)a).name());        //强制类型转型后获取name的值
            System.out.println(((Test)a).age());         //强制类型转型后获取age的值
        }
    }
    

    }

    @Retention(RetentionPolicy.RUNTIME卡塔尔 //保留到运行时,那条十分重点@interface Test{

    public String name();                          //定义两个变量
    public int age();
    

    }

再次表明

  • 重新注脚是Java8新添的效果
  • 再也注脚是值:用多少个相符类其他注释修饰同三个顺序元素
  • 采用重复注脚要分3步走:
    • 概念一个疏解,并用@Repeatable修饰
    • 再定义贰个该注脚的器皿评释
    • 动用重复申明
  • 示例:

    package testpack;

    import java.lang.annotation.Annotation;
    import java.lang.annotation.Repeatable;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;

    @Test(name=”C++”,age=30卡塔尔国@Test(name=”Java”,age=18卡塔尔 //使用了五个雷同类别的注释
    public class Test1 {

    public static void main(String[] args){ 
        Class clazz=Test1.class;
        Annotation[] as=clazz.getAnnotations();
        for (Annotation a:as){
            System.out.println(a);
            //输出:@testpack.Tests(value=[@testpack.Test(name=C++, age=30), @testpack.Test(name=Java, age=18)])  
            //其实还是只有一个注解,就是Tests这个容器注解
    
        }
    
    }
    

    }
    @Repeatable(Tests.class) //用@Repeatable修饰
    @Retention(RetentionPolicy.RUNTIME)
    @interface Test{ //定义Test注解

    public String name();
    public int age();
    

    }
    @Retention(RetentionPolicy.RUNTIME卡塔尔国 //容器注脚的保存时间不可能早于其相应的批注@interface Tests{ //定义Test的器皿注脚Tests

    Test[] value();                    //容器注解的变量
    

    }

体系注明

  • 类型证明也是Java8新扩张效果与利益
  • Java8在先的解说只可以用在一些特定的次序成分上,
  • ElementType.TYPE_PARAMETE奇骏:表示申明能写在项目变量的声明语句中
  • ElementType.TYPE_USE:表示表明能写在使用品类变量的说话中
  • 对该部分内容没什么精晓,更详尽的剧情见:Java
    8的花色注解:工具和时机

APT工具

  • APT(Annotation Processing
    Tool卡塔尔国:一种评释管理工科具,用于对源代码文件举办检查评定,搜索特定的注释音信,然后开展专门的管理
  • 例如说能够在编写翻译源代码的还要,生成一些直属的叙说文件,
  • 在用javac.exe编写翻译源代码时,能够用“-processor”选项钦赐评释微机
  • 评释微型机常常完成javax.annotation.processing.Processor接口也许一而再AbstractProcessor抽象类
  • 八个批注微处理机,能够管理贰个或多少个注解

其他

  • 表明在增高支付效用方面,效率相当大
  • 参考:Java
    8的品种申明:工具和时机
You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图