Java注解解析-Java-优质IT资源分享社区

admin
管理员
管理员
  • UID1
  • 粉丝27
  • 关注4
  • 发帖数581
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:202回复:0

  Java注解解析

楼主#
更多 发布于:2016-05-31 16:43

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答应子类承继父类的注解

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 “”;

}

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。

4. JDK1.8注解增强

TYPE_PARAMETER和TYPE_USE

在JDK1.8中ElementType多了两个枚举成员,TYPE_PARAMETER和TYPE_USE,他们都是用来限制哪个类型能够进行注解。举例来说,假如想要对泛型的类型参数进行注解:

public class

AnnotationTypeParameter<@testtypeparam t=""> {}

那么,在界说@TestTypeParam时,有必要在@Target设置ElementType.TYPE_PARAMETER,表明这个注解能够用来标示类型参数。例如:

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

ClassfilterClassClass =

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

自创文章转发请注明出处:Java注解全面解析

优质IT资源分享社区为你提供此文。

本站有大量优质Java教程视频,资料等资源,包含java基础教程,高级进阶教程等等,教程视频资源涵盖传智播客,极客学院,达内,北大青鸟,猎豹网校等等IT职业培训机构的培训教学视频,价值巨大。欢迎点击下方链接查看。

java教程视频

优质IT资源分享社区(www.itziyuan.top)
一个免费,自由,开放,共享,平等,互助的优质IT资源分享网站。
专注免费分享各大IT培训机构最新培训教学视频,为你的IT学习助力!

!!!回帖受限制请看点击这里!!!
!!!资源失效请在此版块发帖说明!!!

[PS:按 CTRL+D收藏本站网址~]

——“优质IT资源分享社区”管理员专用签名~

本版相似帖子

游客