当前位置:首页 » 编程语言 » java注解定义

java注解定义

发布时间: 2022-11-25 23:14:26

java注解是怎么实现的

注解的使用一般是与java的反射一起使用,下面是一个例子
注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
自定义注解及其应用
1)、定义一个最简单的注解
public @interface MyAnnotation {
//......
}
2)、把注解加在某个类上:
@MyAnnotation
public class AnnotationTest{
//......
}
以下为模拟案例
自定义注解@MyAnnotation
1 package com.ljq.test;
2
3 import java.lang.annotation.ElementType;
4 import java.lang.annotation.Retention;
5 import java.lang.annotation.RetentionPolicy;
6 import java.lang.annotation.Target;
7
8 /**
9 * 定义一个注解
10 *
11 *
12 * @author jiqinlin
13 *
14 */
15 //Java中提供了四种元注解,专门负责注解其他的注解,分别如下
16
17 //@Retention元注解,表示需要在什么级别保存该注释信息(生命周期)。可选的RetentionPoicy参数包括:
18 //RetentionPolicy.SOURCE: 停留在java源文件,编译器被丢掉
19 //RetentionPolicy.CLASS:停留在class文件中,但会被VM丢弃(默认)
20 //RetentionPolicy.RUNTIME:内存中的字节码,VM将在运行时也保留注解,因此可以通过反射机制读取注解的信息
21
22 //@Target元注解,默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括
23 //ElementType.CONSTRUCTOR: 构造器声明
24 //ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
25 //ElementType.LOCAL_VARIABLE: 局部变量声明
26 //ElementType.METHOD: 方法声明
27 //ElementType.PACKAGE: 包声明
28 //ElementType.PARAMETER: 参数声明
29 //ElementType.TYPE: 类、接口(包括注解类型)或enum声明
30
31 //@Documented将注解包含在JavaDoc中
32
33 //@Inheried允许子类继承父类中的注解
34
35
36 @Retention(RetentionPolicy.RUNTIME)
37 @Target({ElementType.METHOD, ElementType.TYPE})
38 public @interface MyAnnotation {
39 //为注解添加属性
40 String color();
41 String value() default "我是林计钦"; //为属性提供默认值
42 int[] array() default {1, 2, 3};
43 Gender gender() default Gender.MAN; //添加一个枚举
44 MetaAnnotation metaAnnotation() default @MetaAnnotation(birthday="我的出身日期为1988-2-18");
45 //添加枚举属性
46
47 }
注解测试类AnnotationTest
1 package com.ljq.test;
2
3 /**
4 * 注解测试类
5 *
6 *
7 * @author jiqinlin
8 *
9 */
10 //调用注解并赋值
11 @MyAnnotation(metaAnnotation=@MetaAnnotation(birthday = "我的出身日期为1988-2-18"),color="red", array={23, 26})
12 public class AnnotationTest {
13
14 public static void main(String[] args) {
15 //检查类AnnotationTest是否含有@MyAnnotation注解
16 if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){
17 //若存在就获取注解
18 MyAnnotation annotation=(MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);
19 System.out.println(annotation);
20 //获取注解属性
21 System.out.println(annotation.color());
22 System.out.println(annotation.value());
23 //数组
24 int[] arrs=annotation.array();
25 for(int arr:arrs){
26 System.out.println(arr);
27 }
28 //枚举
29 Gender gender=annotation.gender();
30 System.out.println("性别为:"+gender);
31 //获取注解属性
32 MetaAnnotation meta=annotation.metaAnnotation();
33 System.out.println(meta.birthday());
34 }
35 }
36 }
枚举类Gender,模拟注解中添加枚举属性
1 package com.ljq.test;
2 /**
3 * 枚举,模拟注解中添加枚举属性
4 *
5 * @author jiqinlin
6 *
7 */
8 public enum Gender {
9 MAN{
10 public String getName(){return "男";}
11 },
12 WOMEN{
13 public String getName(){return "女";}
14 }; //记得有“;”
15 public abstract String getName();
16 }
注解类MetaAnnotation,模拟注解中添加注解属性
1 package com.ljq.test;
2
3 /**
4 * 定义一个注解,模拟注解中添加注解属性
5 *
6 * @author jiqinlin
7 *
8 */
9 public @interface MetaAnnotation {
10 String birthday();
11 }

㈡ java注释的自定义

它类似于新创建一个接口类文件,但为了区分,我们需要将它声明为@interface,如下例:
Java代码
packagecom.iwtxokhtd.annotation;
public@interfaceNewAnnotation {
}
使用自定义的注解类型
Java代码
packagecom.iwtxokhtd.annotation;
publicclassAnnotationTest {
@NewAnnotation
publicstaticvoidmain(String[] args) {
}
}
为自定义注解添加变量
Java代码
packagecom.iwtxokhtd.annotation;
public@interfaceAnnotation {
String value();
}
Java代码
publicclassAnnotationTest {
@NewAnnotation(main method)
publicstaticvoidmain(String[] args) {
saying();
}
@NewAnnotation(value = say method)
publicstaticvoidsaying() {
}
}
定义一个枚举类型,然后将参数设置为该枚举类型,并赋予默认值
public@interfaceGreeting {
publicenum FontColor {
BLUE,RED,GREEN
};
String name();
FontColor fontColor()defaultFontColor.RED;
}
这里有两种选择,其实变数也就是在赋予默认值的参数上,我们可以选择使用该默认值,也可以重新设置一个值来替换默认值
Java代码
publicclassAnnotationTest {
@NewAnnotation(main method)
publicstaticvoidmain(String[] args) {
saying();
sayHelloWithDefaultFontColor();
sayHelloWithRedFontColor();
}
@NewAnnotation(say method)
publicstaticvoidsaying() {
}
// 此时的fontColor为默认的RED
@Greeting(name = defaultfontcolor)
() {
}
@Greeting(name = notdefault, fontColor = Greeting.FontColor.BLUE)
() {
} 1.1. 限制注解的使用范围
用@Target指定ElementType属性
Java代码(jdk)
packagejava.lang.annotation;
public enum ElementType {
TYPE,
// 用于类,接口,枚举但不能是注解
FIELD,
// 字段上,包括枚举值
METHOD,
// 方法,不包括构造方法
PARAMETER,
// 方法的参数
CONSTRUCTOR,
//构造方法
LOCAL_VARIABLE,
// 本地变量或catch语句
ANNOTATION_TYPE,
// 注解类型(无数据)
PACKAGE
// Java包
}
1.2. 注解保持性策略
Java代码
//限制注解使用范围
@Target({ElementType.METHOD,ElementType.CONSTRUCTOR})
public @interface Greeting {
//使用枚举类型
public enum FontColor{
BLUE,RED,GREEN
};
String name();
FontColor fontColor() defaultFontColor.RED;
}
在Java编译器编译时,它会识别在源代码里添加的注解是否还会保留,这就是RetentionPolicy。下面是Java定义的RetentionPolicy枚举:
编译器的处理有三种策略:
将注解保留在编译后的类文件中,并在第一次加载类时读取它
将注解保留在编译后的类文件中,但是在运行时忽略它
按照规定使用注解,但是并不将它保留到编译后的类文件中
Java代码
packagejava.lang.annotation;
public enum RetentionPolicy{
SOURCE,
// 此类型会被编译器丢弃
CLASS,
// 此类型注解会保留在class文件中,但JVM会忽略它
RUNTIME
// 此类型注解会保留在class文件中,JVM会读取它
}
Java代码
//让保持性策略为运行时态,即将注解编码到class文件中,让虚拟机读取
@Retention(RetentionPolicy.RUNTIME)
public @interface Greeting {
//使用枚举类型
public enum FontColor{
BLUE,RED,GREEN
};
String name();
FontColor fontColor() defaultFontColor.RED;
}
1.3. 文档化功能
Java提供的Documented元注解跟Javadoc的作用是差不多的,其实它存在的好处是开发人员可以定制Javadoc不支持的文档属性,并在开发中应用。它的使用跟前两个也是一样的,简单代码示例如下:
Java代码
//让它定制文档化功能
//使用此注解时必须设置RetentionPolicy为RUNTIME
@Documented
public @interface Greeting {
//使用枚举类型
public enum FontColor{
BLUE,RED,GREEN
};
String name();
FontColor fontColor() defaultFontColor.RED;
}
1.4. 标注继承
Java代码
//让它允许继承,可作用到子类
@Inherited
public @interface Greeting {
//使用枚举类型
public enum FontColor{
BLUE,RED,GREEN
};
String name();
FontColor fontColor() defaultFontColor.RED;
}
2. 读取注解信息
属于重点,在系统中用到注解权限时非常有用,可以精确控制权限的粒度
注意:要想使用反射去读取注解,必须将Retention的值选为Runtime
Java代码
packagecom.iwtxokhtd.annotation;
importjava.lang.annotation.Annotation;
importjava.lang.reflect.Method;
//读取注解信息
{
publicstaticvoidmain(String[] args)throws Exception {
// 测试AnnotationTest类,得到此类的类对象
Class c = Class.forName(com.iwtxokhtd.annotation.AnnotationTest);
// 获取该类所有声明的方法
Method[] methods =c.getDeclaredMethods();
// 声明注解集合
Annotation[] annotations;
// 遍历所有的方法得到各方法上面的注解信息
for(Method method : methods) {
// 获取每个方法上面所声明的所有注解信息
annotations =method.getDeclaredAnnotations();
// 再遍历所有的注解,打印其基本信息
System.out.println(method.getName());
for(Annotation an :annotations) {
System.out.println(方法名为: + method.getName()+ 其上面的注解为:
+an.annotationType().getSimpleName());
Method[] meths =an.annotationType().getDeclaredMethods();
// 遍历每个注解的所有变量
for(Method meth :meths) {
System.out.println(注解的变量名为: + meth.getName 注释有三种:// /* */ /** */ 前两种编译器直接跳过,从来不阅读,第三种编译器是可以看懂的,当你使用javadoc这样的命令时会用到,用来生成API时用的。
注解:这东东完全就是给编译器看的。 比如@Ovrride表示这个方法是重写了父类中的方法,而不是自定义的,所以这个时候编译器会去检查你的方法名是否和父类一样,是否写错了。
以上是不同的概念

㈢ java开发中常用的注解有哪些

Java 注解全面解析,学习java做一个java工程师不但待遇高,而且前途无可限量。为什么这样说呢?因为java程序语言作为最流行的计算机开发语言之一,几乎所有的系统、软件、app、网页等都是需要用到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<? 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

望采纳!

㈣ Java ,自定义注解怎么使用

java中自定义注解的使用方法:
首先声明一个接口,并未它添加注解内容!
package testAnnotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Person{
String name();
int age();
}
2、然后利用反射机制查看类的注解内容
package testAnnotation;

@Person(name="xingoo",age=25)
public class test3 {
public static void print(Class c){
System.out.println(c.getName());

//java.lang.Class的getAnnotation方法,如果有注解,则返回注解。否则返回null
Person person = (Person)c.getAnnotation(Person.class);

if(person != null){
System.out.println("name:"+person.name()+" age:"+person.age());
}else{
System.out.println("person unknown!");
}
}
public static void main(String[] args){
test3.print(test3.class);
}
}
运行结果,读取到了注解的内容
testAnnotation.test3
name:xingoo age:25

㈤ java注解的类型可以是哪些

使用注解

在一般的Java开发中,最常接触到的可能就是@Override和@SupressWarnings这两个注解了。使用@Override的时候只需要一个简单的声明即可。这种称为标记注解(marker annotation ),它的出现就代表了某种配置语义。而其它的注解是可以有自己的配置参数的。配置参数以名值对的方式出现。使用 @SupressWarnings的时候需要类似@SupressWarnings({"uncheck", "unused"})这样的语法。在括号里面的是该注解可供配置的值。由于这个注解只有一个配置参数,该参数的名称默认为value,并且可以省略。而花括号则表示是数组类型。在JPA中的@Table注解使用类似@Table(name = "Customer", schema = "APP")这样的语法。从这里可以看到名值对的用法。在使用注解时候的配置参数的值必须是编译时刻的常量。

从某种角度来说,可以把注解看成是一个XML元素,该元素可以有不同的预定义的属性。而属性的值是可以在声明该元素的时候自行指定的。在代码中使用注解,就相当于把一部分元数据从XML文件移到了代码本身之中,在一个地方管理和维护。


开发注解

在一般的开发中,只需要通过阅读相关的API文档来了解每个注解的配置参数的含义,并在代码中正确使用即可。在有些情况下,可能会需要开发自己的注解。这在库的开发中比较常见。注解的定义有点类似接口。下面的代码给出了一个简单的描述代码分工安排的注解。通过该注解可以在源代码中记录每个类或接口的分工和进度情况。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public@interfaceAssignment{
Stringassignee();
inteffort();
doublefinished()default0;
}

@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型。可以通过default来声明参数的默认值。在这里可以看到@Retention和@Target这样的元注解,用来声明注解本身的行为。@Retention用来声明注解的保留策略,有CLASS、RUNTIME和SOURCE这三种,分别表示注解保存在类文件、JVM运行时刻和源代码中。只有当声明为RUNTIME的时候,才能够在运行时刻通过反射API来获取到注解的信息。@Target用来声明注解可以被添加在哪些类型的元素上,如类型、方法和域等。


处理注解

在程序中添加的注解,可以在编译时刻或是运行时刻来进行处理。在编译时刻处理的时候,是分成多趟来进行的。如果在某趟处理中产生了新的Java源文件,那么就需要另外一趟处理来处理新生成的源文件。如此往复,直到没有新文件被生成为止。在完成处理之后,再对Java代码进行编译。JDK 5中提供了apt工具用来对注解进行处理。apt是一个命令行工具,与之配套的还有一套用来描述程序语义结构的Mirror API。Mirror API(com.sun.mirror.*)描述的是程序在编译时刻的静态结构。通过Mirror API可以获取到被注解的Java类型元素的信息,从而提供相应的处理逻辑。具体的处理工作交给apt工具来完成。编写注解处理器的核心是AnnotationProcessorFactory和AnnotationProcessor两个接口。后者表示的是注解处理器,而前者则是为某些注解类型创建注解处理器的工厂。

以上面的注解Assignment为例,当每个开发人员都在源代码中更新进度的话,就可以通过一个注解处理器来生成一个项目整体进度的报告。 首先是注解处理器工厂的实现。

{
(Set<AnnotationTypeDeclaration>atds,?){
if(atds.isEmpty()){
returnAnnotationProcessors.NO_OP;
}
returnnewAssignmentAp(env);//返回注解处理器
}
publicCollection<String>supportedAnnotationTypes(){
returnCollections.unmodifiableList(Arrays.asList("annotation.Assignment"));
}
publicCollection<String>supportedOptions(){
returnCollections.emptySet();
}
}

AnnotationProcessorFactory接口有三个方法:getProcessorFor是根据注解的类型来返回特定的注解处理器;supportedAnnotationTypes是返回该工厂生成的注解处理器所能支持的注解类型;supportedOptions用来表示所支持的附加选项。在运行apt命令行工具的时候,可以通过-A来传递额外的参数给注解处理器,如-Averbose=true。当工厂通过 supportedOptions方法声明了所能识别的附加选项之后,注解处理器就可以在运行时刻通过的getOptions方法获取到选项的实际值。注解处理器本身的基本实现如下所示。

{
private;
;
publicAssignmentAp(){
this.env=env;
assignmentDeclaration=(AnnotationTypeDeclaration)env.getTypeDeclaration("annotation.Assignment");
}
publicvoidprocess(){
Collection<Declaration>declarations=env.getDeclarationsAnnotatedWith(assignmentDeclaration);
for(Declarationdeclaration:declarations){
processAssignmentAnnotations(declaration);
}
}
(Declarationdeclaration){
Collection<AnnotationMirror>annotations=declaration.getAnnotationMirrors();
for(AnnotationMirrormirror:annotations){
if(mirror.getAnnotationType().getDeclaration().equals(assignmentDeclaration)){
Map<,AnnotationValue>values=mirror.getElementValues();
Stringassignee=(String)getAnnotationValue(values,"assignee");//获取注解的值
}
}
}
}

注解处理器的处理逻辑都在process方法中完成。通过一个声明(Declaration)的getAnnotationMirrors方法就可以获取到该声明上所添加的注解的实际值。得到这些值之后,处理起来就不难了。

在创建好注解处理器之后,就可以通过apt命令行工具来对源代码中的注解进行处理。 命令的运行格式是apt -classpath bin -factory annotation.apt.AssignmentApf src/annotation/work/*.java,即通过-factory来指定注解处理器工厂类的名称。实际上,apt工具在完成处理之后,会自动调用javac来编译处理完成后的源代码。

JDK 5中的apt工具的不足之处在于它是Oracle提供的私有实现。在JDK 6中,通过JSR 269把自定义注解处理器这一功能进行了规范化,有了新的javax.annotation.processing这个新的API。对Mirror API也进行了更新,形成了新的javax.lang.model包。注解处理器的使用也进行了简化,不需要再单独运行apt这样的命令行工具,Java编译器本身就可以完成对注解的处理。对于同样的功能,如果用JSR 269的做法,只需要一个类就可以了。

@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("annotation.Assignment")
{
;
publicsynchronizedvoidinit(){
super.init(processingEnv);
ElementselementUtils=processingEnv.getElementUtils();
assignmentElement=elementUtils.getTypeElement("annotation.Assignment");
}
publicbooleanprocess(Set<?extendsTypeElement>annotations,RoundEnvironmentroundEnv){
Set<?extendsElement>elements=roundEnv.getElementsAnnotatedWith(assignmentElement);
for(Elementelement:elements){
processAssignment(element);
}
}
privatevoidprocessAssignment(Elementelement){
List<?extendsAnnotationMirror>annotations=element.getAnnotationMirrors();
for(AnnotationMirrormirror:annotations){
if(mirror.getAnnotationType().asElement().equals(assignmentElement)){
Map<?extendsExecutableElement,?extendsAnnotationValue>values=mirror.getElementValues();
Stringassignee=(String)getAnnotationValue(values,"assignee");//获取注解的值
}
}
}
}

仔细比较上面两段代码,可以发现它们的基本结构是类似的。不同之处在于JDK 6中通过元注解@SupportedAnnotationTypes来声明所支持的注解类型。另外描述程序静态结构的javax.lang.model包使用了不同的类型名称。使用的时候也更加简单,只需要通过javac -processor annotation.pap.AssignmentProcess Demo1.java这样的方式即可。

上面介绍的这两种做法都是在编译时刻进行处理的。而有些时候则需要在运行时刻来完成对注解的处理。这个时候就需要用到Java的反射API。反射API提供了在运行时刻读取注解信息的支持。不过前提是注解的保留策略声明的是运行时。Java反射API的AnnotatedElement接口提供了获取类、方法和域上的注解的实用方法。比如获取到一个Class类对象之后,通过getAnnotation方法就可以获取到该类上添加的指定注解类型的注解。


实例分析

下面通过一个具体的实例来分析说明在实践中如何来使用和处理注解。假定有一个公司的雇员信息系统,从访问控制的角度出发,对雇员的工资的更新只能由具有特定角色的用户才能完成。考虑到访问控制需求的普遍性,可以定义一个注解来让开发人员方便的在代码中声明访问控制权限。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public@interfaceRequiredRoles{
String[]value();
}

下一步则是如何对注解进行处理,这里使用的Java的反射API并结合动态代理。下面是动态代理中的InvocationHandler接口的实现。

<T>implementsInvocationHandler{
finalTaccessObj;
publicAccessInvocationHandler(TaccessObj){
this.accessObj=accessObj;
}
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
RequiredRolesannotation=method.getAnnotation(RequiredRoles.class);//通过反射API获取注解
if(annotation!=null){
String[]roles=annotation.value();
Stringrole=AccessControl.getCurrentRole();
if(!Arrays.asList(roles).contains(role)){
(".");
}
}
returnmethod.invoke(accessObj,args);
}
}

在具体使用的时候,首先要通过Proxy.newProxyInstance方法创建一个EmployeeGateway的接口的代理类,使用该代理类来完成实际的操作。

㈥ Java自定义注解

你的注解是定义在 com.bestTeam.ifu.annotation这个包下的

可是你引用的时候,怎么变成 com$annotation$ValidIdentitySign 这个了?确认你在使用的时候没有写错?

㈦ java内部注解是如何实现的

用一个词就可以描述注解,那就是元数据,即一种描述数据的数据。所以,可以说注解就是源代码的元数据。比如,下面这段代码:

@Override
public String toString() {
return "This is String Representation of current object.";
}

上面的代码中,我重写了toString()方法并使用了@Override注解。但是,即使我不使用@Override注解标记代码,程序也能够正常执行。那么,该注解表示什么?这么写有什么好处吗?事实上,@Override告诉编译器这个方法是一个重写方法(描述方法的元数据),如果父类中不存在该方法,编译器便会报错,提示该方法没有重写父类中的方法。如果我不小心拼写错误,例如将toString()写成了toStrring(){double r},而且我也没有使用@Override注解,那程序依然能编译运行。但运行结果会和我期望的大不相同。现在我们了解了什么是注解,并且使用注解有助于阅读程序。
Annotation是一种应用于类、方法、参数、变量、构造器及包声明中的特殊修饰符。它是一种由JSR-175标准选择用来描述元数据的一种工具。
为什么要引入注解?
使用Annotation之前(甚至在使用之后),XML被广泛的应用于描述元数据。不知何时开始一些应用开发人员和架构师发现XML的维护越来越糟糕了。他们希望使用一些和代码紧耦合的东西,而不是像XML那样和代码是松耦合的(在某些情况下甚至是完全分离的)代码描述。如果你在Google中搜索“XML vs. annotations”,会看到许多关于这个问题的辩论。最有趣的是XML配置其实就是为了分离代码和配置而引入的。上述两种观点可能会让你很疑惑,两者观点似乎构成了一种循环,但各有利弊。下面我们通过一个例子来理解这两者的区别。
假如你想为应用设置很多的常量或参数,这种情况下,XML是一个很好的选择,因为它不会同特定的代码相连。如果你想把某个方法声明为服务,那么使用Annotation会更好一些,因为这种情况下需要注解和方法紧密耦合起来,开发人员也必须认识到这点。
另一个很重要的因素是Annotation定义了一种标准的描述元数据的方式。在这之前,开发人员通常使用他们自己的方式定义元数据。例如,使用标记interfaces,注释,transient关键字等等。每个程序员按照自己的方式定义元数据,而不像Annotation这种标准的方式。
目前,许多框架将XML和Annotation两种方式结合使用,平衡两者之间的利弊。
Annotation是如何工作的?怎么编写自定义的Annotation?
在讲述这部分之前,建议你首先下载Annotation的示例代码AnnotationsSample.zip 。下载之后放在你习惯使用的IDE中,这些代码会帮助你更好的理解Annotation机制。
编写Annotation非常简单,可以将Annotation的定义同接口的定义进行比较。我们来看两个例子:一个是标准的注解@Override,另一个是用户自定义注解@Todo。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

对于@Override注释你可能有些疑问,它什么都没做,那它是如何检查在父类中有一个同名的函数呢。当然,不要惊讶,我是逗你玩的。@Override注解的定义不仅仅只有这么一点代码。这部分内容很重要,我不得不再次重复:Annotations仅仅是元数据,和业务逻辑无关。理解起来有点困难,但就是这样。如果Annotations不包含业务逻辑,那么必须有人来实现这些逻辑。元数据的用户来做这个事情。Annotations仅仅提供它定义的属性(类/方法/包/域)的信息。Annotations的用户(同样是一些代码)来读取这些信息并实现必要的逻辑。
当我们使用Java的标注Annotations(例如@Override)时,JVM就是一个用户,它在字节码层面工作。到这里,应用开发人员还不能控制也不能使用自定义的注解。因此,我们讲解一下如何编写自定义的Annotations。
我们来逐个讲述编写自定义Annotations的要点。上面的例子中,你看到一些注解应用在注解上。
J2SE5.0版本在 java.lang.annotation提供了四种元注解,专门注解其他的注解:
@Documented –注解是否将包含在JavaDoc中
@Retention –什么时候使用该注解
@Target? –注解用于什么地方
@Inherited – 是否允许子类继承该注解
@Documented–一个简单的Annotations标记注解,表示是否将注解信息添加在java文档中。
@Retention– 定义该注解的生命周期。
RetentionPolicy.SOURCE – 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
RetentionPolicy.CLASS – 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
RetentionPolicy.RUNTIME– 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
@Target – 表示该注解用于什么地方。如果不明确指出,该注解可以放在任何地方。以下是一些可用的参数。需要说明的是:属性的注解是兼容的,如果你想给7个属性都添加注解,仅仅排除一个属性,那么你需要在定义target包含所有的属性。
ElementType.TYPE:用于描述类、接口或enum声明
ElementType.FIELD:用于描述实例变量
ElementType.METHOD
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE 另一个注释
ElementType.PACKAGE 用于记录java文件的package信息
@Inherited – 定义该注释和子类的关系
那么,注解的内部到底是如何定义的呢?Annotations只支持基本类型、String及枚举类型。注释中所有的属性被定义成方法,并允许提供默认值。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Todo {
public enum Priority {LOW, MEDIUM, HIGH}
public enum Status {STARTED, NOT_STARTED}
String author() default "Yash";
Priority priority() default Priority.LOW;
Status status() default Status.NOT_STARTED;
}

下面的例子演示了如何使用上面的注解。

@Todo(priority = Todo.Priority.MEDIUM, author = "Yashwant", status = Todo.Status.STARTED)
public void incompleteMethod1() {
//Some business logic is written
//But it’s not complete yet
}

如果注解中只有一个属性,可以直接命名为“value”,使用时无需再标明属性名。

@interface Author{
String value();
}
@Author("Yashwant")
public void someMethod() {
}

但目前为止一切看起来都还不错。我们定义了自己的注解并将其应用在业务逻辑的方法上。现在我们需要写一个用户程序调用我们的注解。这里我们需要使用反射机制。如果你熟悉反射代码,就会知道反射可以提供类名、方法和实例变量对象。所有这些对象都有getAnnotation()这个方法用来返回注解信息。我们需要把这个对象转换为我们自定义的注释(使用 instanceOf()检查之后),同时也可以调用自定义注释里面的方法。看看以下的实例代码,使用了上面的注解:

Class businessLogicClass = BusinessLogic.class;
for(Method method : businessLogicClass.getMethods()) {
Todo todoAnnotation = (Todo)method.getAnnotation(Todo.class);
if(todoAnnotation != null) {
System.out.println(" Method Name : " + method.getName());
System.out.println(" Author : " + todoAnnotation.author());
System.out.println(" Priority : " + todoAnnotation.priority());
System.out.println(" Status : " + todoAnnotation.status());
}

㈧ Java注解的出现 Java的注解是从何开始的

我不知道知道谁发明了注解,但是可以告诉你,java不同版本间的功能定义是不同的。这个功能的定义不是个人决定的,而是一个叫做JCP的组织,
这个组织云集了众多的资深专家,包括顶级开发团队中的精英。从java5开始出现了注解这个概念。定义注解的标准是JSR-250。注解从一定程度上分担了xml配置的一些任务(配套的标准如:JPA)。甚至可以在项目中用纯注解来配置。几乎所有的主流框架(除了struts1)都有自己的一套注解。追溯注解的源头,我个人认为,注解的前身就是我们看到的注释文档。标准的注释文档中有包括@author等的标注。在注解之前我们可以用Xdoclet来进行项目的配置。可惜这一方法几乎没有得到应用。但是注解的出现改变了这一现状。注解易于定义,包括本身就是java,提供了很好的编译器支持。我们可以用注解配置对象。这个是xml文件无法做到的。因为注解的易配置性和强灵活性,还有对代码的执行并不产生影响。注解得到了广泛的应用。现在,新的项目开发都开始倾向于注解这种新的开发方式,在开发的效率和纠错性上面。他已经远远优于xml配置。加上主流框架的支持及其它的易于实现性。相信他会走的更好。

㈨ java中常用注解分别是什么及汉语意思!

Annotation(注解)是JDK5.0及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。注释是以‘@注释名’在代码中存在的,根据注释参数的个数,我们可以将注释分为:标记注释、单值注释、完整注释三类。它们都不会直接影响到程序的语义,只是作为注释(标识)存在,我们可以通过反射机制编程实现对这些元数据的访问。另外,你可以在编译时选择代码里的注释是否只存在于源代码级,或者它也能在class文件中出现。

元数据的作用
如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类:
编写文档:通过代码里标识的元数据生成文档。
代码分析:通过代码里标识的元数据对代码进行分析。
编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查。

基本内置注解

@Override java中覆写
@Deprecated的作用是对不应该在使用的方法添加注释,当编程人员使用这些方法时,将会在编译时显示提示信息,它与javadoc里的
@deprecated标记有相同的功能,准确的说,它还不如javadoc
@deprecated,因为它不支持参数

@SuppressWarnings,其参数有:
deprecation,使用了过时的类或方法时的警告
unchecked,执行了未检查的转换时的警告
fallthrough,当 Switch 程序块直接通往下一种情况而没有 Break 时的警告
path,在类路径、源文件路径等中有不存在的路径时的警告
serial,当在可序列化的类上缺少 serialVersionUID 定义时的警告
finally ,任何 finally 子句不能正常完成时的警告
all,关于以上所有情况的警告

自定义注释
它类似于新创建一个接口类文件,但为了区分,我们需要将它声明为@interface,如:public @interface NewAnnotation {}............

㈩ 深入浅出Java注解 / Java注解是如何工作的

给java注解下个定义
用一个词就可以描述注解,那就是元数据,即一种描述数据的数据。所以,可以说注解就是源代码的元数据。Annotation是一种应用于类、方法、参数、变量、构造器及包声明中的特殊修饰符。它是一种由JSR-175标准选择用来描述元数据的一种工具。
注解的本质
Annotations仅仅是元数据,和业务逻辑无关。理解起来有点困难,但就是这样。如果Annotations不包含业务逻辑,那么必须有人来实现这些逻辑。元数据的"使用者"来做这个事情。Annotations仅仅提供它定义的属性(类/方法/包/域)的信息。Annotations的"使用者"(同样是一些代码)来读取这些信息并实现必要的逻辑。当我们使用Java的标注Annotations(例如@Override)时,JVM就是一个“使用者”,它在字节码层面工作。mok:"当我们使用用于Servlet的注解(例如@WebInitParam)时,容器就是一个'使用者';当我们使用框架提供的注解时,框架中的某个组件会负责做读取后的逻辑处理。"

热点内容
编程好软件 发布:2025-01-16 20:38:07 浏览:422
流量密码如何改成 发布:2025-01-16 20:37:13 浏览:49
java判断是否是对象 发布:2025-01-16 20:31:04 浏览:884
python调用外部程序 发布:2025-01-16 20:14:09 浏览:396
缓解压力英语作文 发布:2025-01-16 20:13:31 浏览:64
javaname 发布:2025-01-16 20:13:15 浏览:21
用户访问表空间 发布:2025-01-16 20:07:07 浏览:943
java代码自动编译 发布:2025-01-16 19:58:14 浏览:313
编程很困难 发布:2025-01-16 19:58:09 浏览:673
gg登录源码 发布:2025-01-16 19:58:07 浏览:292