Java 标准注解和元注解

发布时间:2024年01月06日

Java 标准注解

Java 1.5开始自带的标准注解,包括@Override、@Deprecated和@SuppressWarnings:

  • @Override:表示当前的方法定义将覆盖父类中的方法
  • @Deprecated:表示代码被弃用,如果使用了被@Deprecated注解的代码则编译器将发出警告
  • @SuppressWarnings:表示关闭编译器警告信息

@override(熟悉)

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

从它的定义我们可以看到,这个注解可以被用来修饰方法,并且它只在编译时有效,在编译后的class文件中便不再存在。注解告诉编译器被修饰的方法是重写的父类的中的相同签名的方法,编译器会对此做出检查,若发现父类中不存在这个方法或是存在的方法签名不同,则会报错。(检查方法是否为重写方法,否则报错

@Deprecated(了解)

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

从它的定义我们可以看到,它会被文档化,能够保留到运行时,能够修饰构造方法、属性、局部变量、方法、包、参数、类型。这个注解的作用是告诉编译器被修饰的程序元素已被“废弃”,不再建议用户使用。

@SuppressWarnings(熟悉)

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

它能够修饰的程序元素包括类型、属性、方法、参数、构造器、局部变量,只能存活在源码时,取值为String[]。它的作用是告诉编译器忽略指定的警告信息,它可以取的值如下所示:

参数作用
all抑制所有警告
boxing抑制装箱、拆箱操作时候的警告
cast抑制映射相关的警告
dep-ann抑制启用注释的警告
deprecation抑制过期方法警告
fallthrough抑制确在switch中缺失breaks的警告
finally抑制finally模块没有返回的警告
hiding抑制与隐藏变数的区域变数相关的警告
incomplete-switch忽略没有完整的switch语句
nls忽略非nls格式的字符
null忽略对null的操作
rawtype使用generics时忽略没有指定相应的类型
restriction抑制与使用不建议或禁止参照相关的警告
serial忽略在serializable类中没有声明serialVersionUID变量
static-access抑制不正确的静态访问方式警告
synthetic-access抑制子类没有按最优方法访问内部类的警告
unchecked抑制没有进行类型检查操作的警告
unqualified-field-access抑制没有权限访问的域的警告
unused抑制没被使用过的代码的警告

Java 元注解

在JDK 1.5中提供了4个标准的元注解:@Target,@Retention,@Documented,@Inherited, 在JDK 1.8中提供了两个元注解 @Repeatable和@Native。

@Target(熟悉)

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}

Target注解用来描述被它所修饰的注解的使用范围,在定义注解类时使用了@Target 能够更加清晰的知道它能够被用来修饰哪些对象,它的取值范围定义在ElementType 枚举中,枚举如下:

public enum ElementType {
    TYPE, // 类、接口、枚举类
    FIELD, // 成员变量(包括:枚举常量)
    METHOD, // 成员方法
    PARAMETER, // 方法参数
    CONSTRUCTOR, // 构造方法
    LOCAL_VARIABLE, // 局部变量 
    ANNOTATION_TYPE, // 注解类
    PACKAGE, // 包
    TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
    TYPE_USE // 使用类型的任何地方,JDK 1.8 新增
}

@Retention(熟悉)

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

Reteniton注解用来限定那些被它所注解的注解类在注解到其他类上以后,可被保留到何时,一共有三种策略,定义在RetentionPolicy枚举中,枚举如下:

public enum RetentionPolicy {
    SOURCE,  // 当前注解仅保留在源代码中
    CLASS,   // (默认)当前注解保留在编译后的字节码文件中,但不可被反射机制操作
    RUNTIME  // 当前注解保留在编译后的字节码文件中,可被反射机制操作
}

@Documented(了解)

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

Documented注解的作用是:描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息

@Inherited(熟悉)

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

Inherited注解的作用:被它修饰的Annotation将具有继承性。如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解。

@Repeatable(熟悉)

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
    Class<? extends Annotation> value();
}

Repeatable用于注解上,允许同一个程序元素多次使用相同的注解
Repeatable的使用案例如下:

自定义 User 注解类

package com.annotation.repeatable;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Users.class)
public @interface User {
    String value();
}

自定义 Users 注解类(容器注解)

package com.annotation.repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Users {
    User[] value();
}

自定义 MyClass 类

package com.annotation.repeatable;
@User("you")
@User("me")
public class MyClass {
    //...
}

自定义 MyTest 类

package com.annotation.repeatable;
public class MyTest {
    public static void main(String[] args) {
        Class<MyClass> clazz = MyClass.class;
        Users users = clazz.getAnnotation(Users.class);
        if (users != null) {
            for (User user : users.value()) {
                System.out.println(user.value()); // 输出 "you", "me"
            }
        }
    }
}

注意:

  • Users 上需要添加 @Retention(RetentionPolicy.RUNTIME) ,否则 clazz.getAnnotation(Users.class) 无法获取到 Users;
  • MyClass 类上需要添加 两个及以上 @User 注解,否则不会封装到容器注解,也就获取不到 Users 。

@Native(了解)

@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Native {
}

使用 @Native 注解修饰成员变量,则表示这个变量可以被本地代码引用,常常被代码生成工具使用。对于 @Native 注解不常使用,了解即可。

文章来源:https://blog.csdn.net/glb168/article/details/135420343
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。