Java 注解详解
时间:2022-06-04
本文章向大家介绍Java 注解详解,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
简介
注解是在Java 1.5之后引入的,为的是可以直接在代码中编写元信息。在注解发布之前,如果想要描述代码只能将其写入到其他文件中,例如xml。 注解可以应用于包,类,方法,字段,参数,类型(Java 8之后)。注解并不会直接影响代码,它只是为第三方系统提供代码的元信息,第三方系统通过解析这些注解获取信息,从而执行不同的方法。
注解的语法
注解使用@开头,例如
@Annotation
public void annotatedMethod(){
}
注解同样也可以有参数
@Annotation(
info = "I am an annotation",
counter = "55"
)
public void annotatedMehod() {
...
}
如果只有一个参数,参数名可以省略
@Annotation("I am an annotation")
public void annotatedMehod() {
...
}
多个注解可以同时修饰同一个元素
@Annotation (info = "UauO")
@Annotation2
class AnnotatedClass { ... }
用途
注解有多种用途,最常用的几种方式是:
- 提供信息给编译器: 编译器可以分析注解,获取不同的规则产生警告甚至错误。例如Java 8的 @FunctionInterface 注解,如果这个注解修饰的接口包含了2个及以上的方法编译器就会发出错误警告
- 生成文档: 一些特殊的注解处理其可以通过解析特定注解生成文档,例如Jenkins等
- 代码生成: 通过注解提供的信息,自动生成代码,例如JAXB
- 运行时处理: 在运行时分析注解,例如Spring,JPA等
内置注解
Java内置了一些常用的注解,例如下面要介绍的元注解,之所以叫元注解是因为它们是修饰注解的注解
- @Retention 表示注解的声明周期,可选值为:
- SOURCE: 仅存在于源码中,被编译器和JVM忽略
- CLASS: 保存在字节码中,编译器可以获取,JVM忽略
- RUNTIME: 运行时可以获取,整个生命周期都可以获取
- @Target 表示注解可以修饰那些元素
- ANNOTATION_TYPE: 可以修饰注解
- CONSTRUCTOR: 可以修饰构造函数
- FIELD: 可以修饰字段
- LOCAL_VARIABLE: 可以修饰本地变量
- METHOD: 可以修饰方法
- PACKAGE: 可以修饰包
- PARAMETER: 可以修饰方法参数
- TYPE: 可以修饰类
- @Documented: 可以由Javadoc 工具生成文档
- @Inherited: 默认注解是不能被子类继承的,这个注解修饰后注解可以被所有子类继承。
- @Deprecated: 表示被修饰的元素已经被遗弃了,以后不再维护。
- @SuppressWarning: 通知编译器不要为被修饰的元素产生错误
- @Override: 子类重写父类方法。
- @SafeVarargs: 方法或者构造函数的可变参数不会执行不安全的操作,具体可参考@SafeVarargs
- @Repeatable: Java 8提供注解,表示注解可以重复 例如,没有这个注解的之后,同一个注解在同一个元素上使用一次,所以如果包含了多个值需要使用数组的形式 @Retention( RetentionPolicy.RUNTIME ) @Target( ElementType.TYPE_USE ) public @interface RepeatedValues { CanBeRepeated[] value(); } 有了@Repeatable之后可以直接定义这个注解是可以重复使用的 @Retention( RetentionPolicy.RUNTIME ) @Target( ElementType.TYPE_USE ) @Repeatable( RepeatedValues.class ) public @interface CanBeRepeated { String value(); } @CanBeRepeated( "the color is green" ) @CanBeRepeated( "the color is red" ) @CanBeRepeated( "the color is blue" ) public class RepeatableAnnotated { }
- @FunctionInterface: 修饰接口表示其是一个函数式接口,只能包含一个函数声明。
自定义注解
自定义注解的关键字是@interface
例如:
@Retention( RetentionPolicy.RUNTIME )
@Target( ElementType.TYPE )
public @interface CustomAnnotationClass
{
public String author() default "danibuiza";
public String date();
}
上述定义了一个注解CunstomAnnotationClass,它由两个参数author和date,author的默认值是 ‘danibuiza’,这个注解可以修饰类,且在运行时可见。 使用注解
@CustomAnnotationClass( date = "2014-05-05" )
public class AnnotatedClass
{
...
}
java.lang.Class
,java.lang.reflect.Method
,java.lang.reflect.Field
等都实现了getAnnotations(),isANnotationPresent(Annotation),getAnnotation(class)这些方法,这些方法是使用自定义注解的主要方法,例如:
public static void main( String[] args ) throws Exception
{
Class<AnnotatedClass> object = AnnotatedClass.class;
// Retrieve all annotations from the class
Annotation[] annotations = object.getAnnotations();
for( Annotation annotation : annotations )
{
System.out.println( annotation );
}
// Checks if an annotation is present
if( object.isAnnotationPresent( CustomAnnotationClass.class ) )
{
// Gets the desired annotation
Annotation annotation = object.getAnnotation( CustomAnnotationClass.class );
System.out.println( annotation );
}
// the same for all methods of the class
for( Method method : object.getDeclaredMethods() )
{
if( method.isAnnotationPresent( CustomAnnotationMethod.class ) )
{
Annotation annotation = method.getAnnotation( CustomAnnotationMethod.class );
System.out.println( annotation );
}
}
}
运行后输出如下:
@com.danibuiza.javacodegeeks.customannotations.CustomAnnotationClass(getInfo=Info, author=danibuiza, date=2014-05-05)
@com.danibuiza.javacodegeeks.customannotations.CustomAnnotationClass(getInfo=Info, author=danibuiza, date=2014-05-05)
@com.danibuiza.javacodegeeks.customannotations.CustomAnnotationMethod(author=friend of mine, date=2014-06-05, description=annotated method)
@com.danibuiza.javacodegeeks.customannotations.CustomAnnotationMethod(author=danibuiza, date=2014-06-05, description=annotated method)
关于注解的继承问题
如果使用@Inherited修饰注解,那么子类是可以继承父类的注解的,但是这仅仅对于继承类的时候才有用,如果是实现接口,那么继承不再有效,例如:
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface InheritedAnnotation
{
}
@InheritedAnnotation
public class AnnotatedSuperClass
{
public void oneMethod()
{
}
}
public class AnnotatedSubClass extends AnnotatedSuperClass
{
@Override
public void oneMethod(){
}
}
System.out.println( "is true: " + AnnotatedSuperClass.class.isAnnotationPresent( InheritedAnnotation.class ) );
System.out.println( "is true: " + AnnotatedSubClass.class.isAnnotationPresent( InheritedAnnotation.class ) );
输出:
is true: true
is true: true
而对于实现接口:
@InheritedAnnotation
public interface AnnotatedInterface
{
public void oneMethod();
}
public class AnnotatedImplementedClass implements AnnotatedInterface
{
@Override
public void oneMethod()
{
}
}
System.out.println( "is true: " + AnnotatedInterface.class.isAnnotationPresent( InheritedAnnotation.class ) );
System.out.println( "is true: " + AnnotatedImplementedClass.class.isAnnotationPresent( InheritedAnnotation.class ) );
输出如下:
is true: true
is true: false
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 基于OpencvCV的情绪检测
- 设计模式 之 抽象工厂模式
- Angular应用里HTTP请求的错误处理
- 使用npm安装TypeScript
- TypeScript的interface关键字
- TypeScript的class关键字
- TypeScript里一些特殊的类型
- TypeScript的类型断言,有点像ABAP的强制类型转换
- 什么是TypeScript的字符串索引签名
- [初探] proxy 的优势与使用场景
- TypeScript里的interface和class以及对应的JavaScript代码
- TypeScript里的interface扩展,多继承以及对应的JavaScript代码
- TypeScript里的混合类型
- 完全图解 HTTPS
- TypeScript里的完整函数定义语法