这一次我们来看看注解的Annotation接口。
首先我们要知道什么是注解,注解这个特性是java5引入进来的,主要是在代码上附带上元数据或标记。这样的做法使代码与一些框架的配置项很好的结合起来,且增加了代码的可读性,Hibernate注解就是非常成功的使用。
Java本身为我们提供了三个注解,他们分别是
java,lang.Override
@Override注解说明该方法覆盖了父类的某个方法,在编译时编译器将对该方法进行检查,如果出现拼写错误,或父类并没有这个方法将报错。
java,lang.Deprecated
@Deprecated注解说明该类、方法、成员变量已经不再建议使用了,一般IDE会将@Deprecated的类、方法、成员变量划掉以提示开发者。
java,lang.SuppressWarnings
@SuppressWarnings可以消除编译器的warning,在你非常确定一个类、方法、变量的warning是可以忽略的时候,你可以使用这个注解。
那么我们以下面这个超简单的例子来说明注解是如何使用的:
@Deprecated public class Test { }
我们可以看到我们为Test类添加了@Deprecated注解,于是Test被IDE划掉了。在Java中注解可以反射成Annotation的对象,而我们获取Annotation的办法则是通过一个AnnotatedElement接口来实现。Class正好实现了这个接口。
在AnnotatedElement中一共有
<T extends Annotation> T getAnnotation(Class<T> annotationType);
boolean isAnnotationPresent(Class<? extends Annotation> annotationType);
Annotation[] getAnnotations();
Annotation[] getDeclaredAnnotations();
这四个方法。
首先我们就以刚刚那个例子为例,来试一下如何获取类的@Deprecated注解对象
@Deprecated public class Test { public static void main(String[] args) { Annotation aOverride = new Test().getClass().getAnnotation(Override.class); System.out.println("new Test().getClass().getAnnotation(Override.class)=" + aOverride); //输出new Test().getClass().getAnnotation(Override.class)=null Annotation aDeprecated = new Test().getClass().getAnnotation(Deprecated.class); System.out.println("new Test().getClass().getAnnotation(Deprecated.class)=" + aDeprecated); //输出new Test().getClass().getAnnotation(Deprecated.class)=@java.lang.Deprecated() } }
我们可以看到的确把这个Annotation给获取出来了,但我们发现我们必须预先知道注解的类型才能获取出来,那么有没有办法来判断将要获取的注解是什么类型呢?一个简单的思路就是通过调用
boolean isAnnotationPresent(Class<? extends Annotation> annotationType);
方法以及if-else来判断我们的类使用了哪一个注解,从而调用对应的getAnnotation方法
@Deprecated public class Test { public static void main(String[] args) { Class<? extends Test> t = new Test().getClass(); Annotation a; if (t.isAnnotationPresent(Override.class)) { a = t.getAnnotation(Override.class); } else if (t.isAnnotationPresent(Deprecated.class)) { a = t.getAnnotation(Deprecated.class); } else if (t.isAnnotationPresent(SuppressWarnings.class)) { a = t.getAnnotation(SuppressWarnings.class); } else { a = null; } System.out.println("a=" + a);//输出a=@java.lang.Deprecated() } }
在控制台我们可以看到,的确获取了正确的注解对象了。但有时我们需要自行添加一些新的注解,如果按照这样的思路,不断添加if-else语句显然是不科学的。那怎么才能在不知道注解类型的情况下获注解对象呢?AnnotatedElement接口中的getAnnotations方法就解决了这个问题,我们还是以上面的那个例子为例,获取一下@Deprecated注解的对象
@Deprecated public class Test { public static void main(String[] args) { Class<? extends Test> t = new Test().getClass(); Annotation[] arg = t.getAnnotations(); System.out.println("arg.length=" + arg.length);//arg.length=1 Annotation a = arg[0]; System.out.println("a=" + a);//a=@java.lang.Deprecated() } }
在控制台我们看到我们在不知道注解类型的情况下获取了注解对象。
getAnnotations()方法可以帮我们在不知道注解类型的情况下获取在类、方法、变量上面的全部注解。在这我们自定义一个注解为@MyAnnotation
@Inherited @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String hello(); }
然后注解到我们的Test类上,然后调用getAnnotations方法
@Deprecated @MyAnnotation(hello="你好") public class Test { public static void main(String[] args) { Class<? extends Test> t = new Test().getClass(); Annotation[] arg = t.getAnnotations(); System.out.println("arg.length=" + arg.length);//arg.length=2 for (Annotation a : arg) { System.out.println(" a=" + a); } } }
我们看到两个注解的对象都被我们获取回来了。
仔细观察的朋友可能会发现在AnnotatedElement类中还有一个getDeclaredAnnotations方法,它的返回值与getAnnotations方法是一样的。那他们有些什么区别的呢?
首先我们要知道注解是可以继承的,就是说子类会继承父类的一些注解(该注解在定义时一定要声明为@Inherited,而且方法和变量上的注解不一定能继承)。我们再编写一个Test2类来给Test继承
@MyAnnotation(hello="你好") class Test2 { } @Deprecated public class Test extends Test2{ public static void main(String[] args) { Class<? extends Test> t = new Test().getClass(); Annotation[] ta = t.getAnnotations(); System.out.println("ta.length=" + ta.length); for (Annotation temp: ta){ System.out.println(temp); } Annotation[] tda = t.getDeclaredAnnotations(); System.out.println("tda.length=" + tda.length); for (Annotation temp: tda){ System.out.println(temp); } } }
我们可以看到在控制台里面tda只输出了一条信息,而ta则有两条。就是因为tda屏蔽了由Test2继承而来的@Deprecated。
在我们大体知道如何利用反射机制获取注解对象之后,我们来看看Annotation接口都为我们提供了哪些方法。
首先我们来看看equals和hash方法
@MyAnnotation(hello="你好") public class Test{ public static void main(String[] args) { Annotation a1 = new Test().getClass().getAnnotation(MyAnnotation.class); Annotation a2 = new Test2().getClass().getAnnotation(MyAnnotation.class); boolean temp = a1.equals(a2); System.out.println(temp + "=Test的MyAnnotation==Test2的MyAnnotation"); System.out.println("a1=" + a1.hashCode()); System.out.println("a2=" + a2.hashCode()); } } @MyAnnotation(hello="你好") class Test2 { }
从控制台我们发现Annotation对象有这样的规则,只要是相同的注解,不管它注解的是哪个类都将指向同一个空间,这一点有些类似字符串常量的机制。
而Annotation的另一个方法toSting()则只返回Annotation对象的类以及其成员变量,它并没有像Object的成员变量那样既显示出hashcode又显示出对象的类型。
最后在Annotation类里,还有一个比较实用的方法
Class<? extends Annotation> annotationType();
这个方法可以返回当前注解对象的注解类型,这样我们就可以在不知道注解类型的情况下反射获取注解对象并获取出它的类型来进行一些特别的处理了。
@MyAnnotation(hello="你好") public class Test{ public static void main(String[] args) { Annotation a = new Test().getClass().getAnnotations()[0]; Class<? extends Annotation> c = a.annotationType(); System.out.println(c); } }
从上面的这个例子我们可以看到,我们在不知道不了解注解类型的情况情况下取得了注解的对象以及注解类型。
通过这个方法我们就可以进行许多方便有效的注解反射操作了。
相关推荐
3. **Annotation类型**:Annotation类型是一种接口,定义了Annotation的结构和默认值。在Java中,通过`@interface`关键字声明Annotation类型,其中的成员变量是固定的,没有方法参数。当我们通过反射API访问...
自定义Annotation实际上自动继承了`java.lang.annotation.Annotation`接口,但不能继承其他Annotation类型或接口。这使得Annotation成为一种单继承的类型。 总之,Annotation技术是Java编程中的一个强大工具,它...
Java annotation 什么是java annotation?annotation 的7种标注类型。nnotation提供了一条与程序元素关联任何信息或者任何元数据(metadata...annotation类型是一种接口,能够通过java反射API的方式提供对其信息的访问。
赠送jar包:jakarta.annotation-api-1.3.5.jar; 赠送原API文档:jakarta.annotation-api-1.3.5-javadoc.jar; 赠送源代码:jakarta.annotation-api-1.3.5-sources.jar; 赠送Maven依赖信息文件:jakarta.annotation...
赠送jar包:javax.annotation-api-1.2.jar; 赠送原API文档:javax.annotation-api-1.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.2-sources.jar; 赠送Maven依赖信息文件:javax.annotation-api-1.2.pom;...
- **Annotation类型**:定义注解的接口,指定了注解的名称、成员及其默认值。注解类型本质上是一个特殊的接口,其中的方法表示注解的成员,返回类型即为成员的类型。 - **Annotation成员**:注解的成员以无参数的...
赠送jar包:jakarta.annotation-api-1.3.5.jar; 赠送原API文档:jakarta.annotation-api-1.3.5-javadoc.jar; 赠送源代码:jakarta.annotation-api-1.3.5-sources.jar; 赠送Maven依赖信息文件:jakarta.annotation...
Annotation的本质是一种特殊类型的注解,它允许开发者向编译器、JVM或者工具提供关于代码的额外信息,比如接口实现、序列化、代码生成等。 1. **Annotation定义**: Annotation的定义格式通常为`public @interface...
赠送jar包:javax.annotation-api-1.3.2.jar; 赠送原API文档:javax.annotation-api-1.3.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.3.2-sources.jar; 赠送Maven依赖信息文件:javax.annotation-api-...
@androidx.annotation.NonNull 缺失的兼容、androidx.annotation兼容包
javax.annotation-3.0.jar javax.annotation-3.0.jar javax.annotation-3.0.jar
`AnnotationProcessor` 是通过实现`javax.annotation.processing.Processor`接口来创建的。在这个接口中,主要有两个关键方法:`process()` 和 `getSupportedAnnotationTypes()`。`process()` 方法负责处理注解,而`...
`javax.annotation.processing.Processor`接口是注解处理器的核心。通过实现该接口并配置`META-INF/services/javax.annotation.processing.Processor`文件,可以指定编译器何时使用处理器。 ## 五、使用注解 使用...
处理器通过实现`javax.annotation.processing.Processor`接口来实现。 4. **自定义注解** 要创建自定义注解,需要定义一个注解类型,类似于接口,但使用`@interface`关键字。例如: ```java @Retention...
在iOS开发中,Annotation是苹果地图(MapKit)框架中的一个重要概念,用于在地图上添加可视化标记,以展示特定地理位置的信息。自定义的Annotation则允许开发者根据需求个性化地图上的标注,比如添加图片、自定义...
在本例中,我们关注的`jar`包是`javax.annotation.zip`,它包含了`javax.annotation`相关的API,主要用于处理Java的注解(Annotation)。 `javax.annotation`是Java标准版(Java SE)的一部分,提供了标准的注解,...
Compass 是一个全文搜索引擎库,它是对 Lucene 的封装,为 Java 应用提供了一种简单易用的接口。在 Compass 中,Annotation 是一种元数据注解方式,它允许开发者在对象模型上直接定义搜索映射,使得对象与索引之间的...
### 用Annotation简化Java程序的开发 #### 一、引言 随着软件开发技术的不断发展,特别是Java语言的广泛应用,开发者面临着如何有效地管理和配置代码的问题。传统的做法是使用XML文件来配置程序的各种设置,但这种...
- **定义Annotation类型**:类似于接口声明,但使用`@`符号。每个方法定义了一个成员,方法返回类型有限制,可以是基本类型、字符串、类、枚举、注解或它们的数组,并可以有默认值。 ```java public @interface ...