java注解

 

目录

一、介绍

二、注解声明

三、注解使用

四、预定义的注解类型

4.1、被编译器使用的注解

@Deprecated

@Override

@SuppressWarnings

4.2、用于其他注解的注解

@Retention

@Documented

@Target

@Inherited

@Repeatable

五、其他

参考:


一、介绍

注解(annotation),一种元数据,提供一些关于程序的数据,但不是程序的一部分,对程序的执行没有直接的影响。

注解有三种用处:提供信息给编译器,指导编译器行为;提供构建信息给构建工具,这些工具有ant、mavent等,构建工具会根据这些注解产生源码或其他文件;运行时提供信息,可以通过反射来获得这些注解信息。

定义的注解默认继承于java.lang.annotation.Annotation接口,因此你可以继承该注解,但是没多大的实际用处。

二、注解声明

@Retention(RetentionPolicy.RUNTIME)
@interface ClassPreamble {
   String author();
   String date();
   int currentRevision() default 1;
   String lastModified() default "N/A";
   String lastModifiedBy() default "N/A";
   // Note use of array
   String[] reviewers();
}

注解声明与接口类似,多了个@。注解中的元素声明与接口方法类似,元素也可以赋予默认值,通过default实现。注解的元素类型只能是基本类型、数组、字符串、枚举、注解、Class。定义该注解时可以被其他元注解注释,如上面的@Retention,该注解说明自定义的注解ClassPreamble可以保存到运行时。

三、注解使用

注解一般可以使用在类、方法、字段等java元素上,这是在定义注解时声明的通过Target设置的。如:

@Author(
   name = "Benjamin Franklin",
   date = "3/27/2003"
)
class MyClass() { ... }

如果只有一个元素,该元素名字为value的情况下,名字可以忽略:

@SuppressWarnings(value = "unchecked")
void myMethod() { ... }
可以写成如下方式
@SuppressWarnings("unchecked")
void myMethod() { ... }

如果有多个元素,其他的有默认值,value元素没有,也可以忽略其他元素,和value名字:

@MyAnnotation("aaa")
class A<T,Y>{
}
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
	public String value();
	public String name() default "";
}

如果没有元素或者都有默认值,连括号也可以忽略:

@EBook
class MyClass { ... }

如果元素是数组,且赋予数组一个值,则不需要大括号:

@MyAnnotation("aaa")
class A<T,Y>{
}
@MyAnnotation({"bbb","ccc"})
class B{
	
}
@MyAnnotation("aaa","bbb")
class C{

}
@interface MyAnnotation{
	String[] value();
	String[] name() default "bbb";
}

四、预定义的注解类型

java se api中已经定义了一些注解,可以用于编译器和用于其他注解。

4.1、被编译器使用的注解

@Deprecated

告诉编译器被注解的元素是被弃用的,使用会被编译器警告。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

可以看出,@Deprecated可以被使用到很多地方,不局限于方法、类、字段。可以配合javadoc的@deprecated标签使用,通过该标签解释下为何弃用。

   // Javadoc comment follows
    /**
     * @deprecated
     * explanation of why it was deprecated
     */
    @Deprecated
    static void deprecatedMethod() { }
}

@Override

通知编译器被注释的方法必须覆盖父类方法。

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

@SuppressWarnings

用于抑制警告

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

还有其他的如@SafeVarargs、@FunctionalInterface。

4.2、用于其他注解的注解

用于注释其他注解的注解称为元注解。

@Retention

指定被标记的注解如何被存储,比如存在源码中、字节码中、运行时中。如果@Retention不存在,则默认使用RetentionPolicy.CLASS策略,就是存在字节码中。

  • RetentionPolicy.SOURCE – The marked annotation is retained only in the source level and is ignored by the compiler.
  • RetentionPolicy.CLASS – The marked annotation is retained by the compiler at compile time, but is ignored by the Java Virtual Machine (JVM).
  • RetentionPolicy.RUNTIME – The marked annotation is retained by the JVM so it can be used by the runtime environment.
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

@Documented

被@Document注释的注解在其他地方被使用时,可以显示在javadoc导出的文档中。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

@Target

指定注解可以使用在哪种java元素上:

  • ElementType.ANNOTATION_TYPE can be applied to an annotation type.
  • ElementType.CONSTRUCTOR can be applied to a constructor.
  • ElementType.FIELD can be applied to a field or property.
  • ElementType.LOCAL_VARIABLE can be applied to a local variable.
  • ElementType.METHOD can be applied to a method-level annotation.
  • ElementType.PACKAGE can be applied to a package declaration.
  • ElementType.PARAMETER can be applied to the parameters of a method.
  • ElementType.TYPE can be applied to any element of a class.
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}

@Inherited

指示注解可以被继承。假设被@Inherited注释的注解为@A,如果父类被@A注释,子类便可以继承这个注解。但是并不完全对,因为通过反射,子类不能找到@A。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

@Repeatable

被@Repeatable注解的注解可以在一个地方使用多次,比如下面的@Schedule可以使用多次:

@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }

但是由于兼容原因,repeatable注解(就是被@Repeatable注释过的注解)需要被存入容器注解(container annotation)。也就是说定义repeatable注解时还需要定义容器注解。下面声明repeatable注解:

@Repeatable(Schedules.class)
public @interface Schedule {
  String dayOfMonth() default "first";
  String dayOfWeek() default "Mon";
  int hour() default 12;
}

@Repeatable中需要指定容器注解,容器注解的定义为:

public @interface Schedules {
    Schedule[] value();
}

注意,容器注解的元素value数组中的类型一定要为repeatable注解类型。很拗口吧,但是既然要存入repeatable注解(也就是Schedule),当然要定义它的数组(Schedule[])。

五、其他

一些注解可以用于类型的使用上,被称为类型注解(type annotation),通常被用于类型检测。

参考:

https://docs.oracle.com/javase/tutorial/java/annotations/index.html

http://tutorials.jenkov.com/java/annotations.html

https://www.developer.com/java/other/article.php/10936_3556176_3/An-Introduction-to-Java-Annotations.htm

https://blog.usejournal.com/how-much-do-you-actually-know-about-annotations-in-java-b999e100b929

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值