java学习之路01-java注解(Annotation)01-java内置注解

java内置注解

作用在代码的注解

@Override

  • 重写注解,标注在方法上,无属性。

该注解告诉编译器,该方法是重写方法,编译器则会判断其实现的接口或其父类有无该方法,无则编译报错。

@Deprecated

  • 过时注解,标注在属性方法参数构造器局部变量上,无属性。

该注解表示该类或者方法为已经废弃的,只是为了兼容以前的程序,调用处也会出现删除线,不建议使用,建议使用新的方法或者类。

Java 9 中注解增加了两个新属性:
since: 该属性指定已注解的API元素已被弃用的版本。
forRemoval: 改属性表示注解的 API 元素在将来的版本中被删除,应该迁移 API。*

@SuppressWarnings

  • 抑制编译器警告注解,标注在属性方法参数构造器局部变量上,属性为String[] value()

该注解的作用是告诉编译器取消标注代码的指定的警告。
@SuppressWarnings("unchecked") 抑制单类型的警告
@SuppressWarnings({"unchecked","rawtypes"}) 抑制多类型的警告
@SuppressWarnings("all") 抑制所有类型的警告
建议把注解放在最近进警告发生的位置。

@SafeVarargs

  • 抑制堆污染警告注解,标注在构造器方法上,无属性。

该注解的作用是告诉编译器取消unchecked警告。

unchecked警告是什么?
Heap Pollution堆污染,首先我们看下什么是堆污染:

某个 可变泛型参数 指向的对象 并不是该泛型参数,而是无泛型参数。

举个栗子:

	//此时test方法的入参是List<String>
	public static void test(List<String> list) {
	}
	public static void main(String[] args) {
	        List list = Lists.newArrayList();
	        list.add(1);
	        //test方法的入参(可变泛型参数)指向的并不是List<String>,而是List(无泛型参数)
	        test(list);
	}

这种情况就会发生堆污染,此时编译器会提示我们unchecked警告。
java学习之路01-java注解(Annotation)01-java内置注解
而堆污染还可能导致ClassCastException异常,比如在test方法体中添加对List<Integer>的操作。

public static void main(String[] args) {
        List list = Lists.newArrayList();
        list.add(1);
        test(list);
    }

    public static void test(List<String> list) {
        String a = list.get(0);
    }

java学习之路01-java注解(Annotation)01-java内置注解
运行代码抛出ClassCastException异常
所以在使用@SafeVarargs注解时,保证在不会出现ClassCastException异常时,加到方法上以消除警告。

使用的时候要注意:@SafeVarargs注解,对于非static或非final声明的方法,不适用,会编译不通过。

@FunctionalInterface

  • 函数式接口注解,标注在接口上,无属性

该注解只能标志在"有且仅有一个抽象方法"的接口上。
有且仅有一个抽象方法不包括JDK8接口中的静态方法和默认方法,不包括覆盖了Object中方法。
该注解不是必须的,如果一个符合函数式接口要求的接口加不加该注解都可以,但是如果不满足要求加该注解则会编译报错。

举个栗子:

@FunctionalInterface
public interface TestInterface {
	//唯一的抽象方法
    public void test();

    public int hashCode();

    public static void test1(){

    }

}

作用在注解的注解(元注解)

@Target

  • 指定注解的使用范围
  • ElementType.TYPE:类、接口、注解、枚举
  • ElementType.FIELD:字段、枚举常量
  • ElementType.METHOD:方法
  • ElementType.PARAMETER:形式参数
  • ElementType.CONSTRUCTOR:构造方法
  • ElementType.LOCAL_VARIABLE:局部变量
  • ElementType.ANNOTATION_TYPE:注解
  • ElementType.PACKAGE:包
  • ElementType.TYPE_PARAMETER:类型参数

举个栗子:

@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.CLASS)
public @interface TestAnnotation {

}

class Test<@TestAnnotation T> {
    
    public <@TestAnnotation U> U foo(U u) {
        return null;
    }
}
  • ElementType.TYPE_USE:类型使用

可以指定任何类型,举个栗子:

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.CLASS)
public @interface TestAnnotation {

    String value() default "a";

}

@TestAnnotation
@interface TestAnnotation1 {

}

@TestAnnotation
class Test<@TestAnnotation T> {

    @TestAnnotation Test() {
    }

    @TestAnnotation
    private Integer n;

    @TestAnnotation
    public <@TestAnnotation U> U foo(U u) {
        return null;
    }

    @TestAnnotation
    public String fun(@TestAnnotation Integer a) {
        @TestAnnotation
        Integer b = a;
        Object o = (@TestAnnotation Object) a;
        @TestAnnotation String text = (@TestAnnotation String) new Object();
        n = b;
        return "1";
    }

}

注意:当使用 ElementType.TYPE_USE时,方法的返回值若为void,则不可以被使用。
java学习之路01-java注解(Annotation)01-java内置注解

@Retention

  • 用于指定注解的保留策略
  • RetentionPolicy.SOURCE:注解只保留在源码中,在编译时会被编译器丢弃
    栗子:@Override
  • RetentionPolicy.CLASS:(默认的保留策略) 注解会被保留在Class文件中,但不会被加载到虚拟机中,运行时无法获得
  • RetentionPolicy.RUNTIME:注解会被保留在Class文件中,且会被加载到虚拟机中,可以在运行时获得
    栗子:@Deprecated

@Documented

  • 用于将注解包含在javadoc中

javadoc是Sun公司提供的一个技术,它从程序源代码中抽取类、方法、成员等注释形成一个和源代码配套的API帮助文档。也就是说,只要在编写程序时以一套特定的标签作注释,在程序编写完成后,通过Javadoc就可以同时形成程序的开发文档了。

默认情况下,javadoc是不包括注解的,但如果使用了@Documented注解,则相关注解类型信息会被包含在生成的文档中

@Inherited

  • 用于指明父类注解会被子类继承得到

举个栗子:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface TestAnnotation {

    String value();

}

@TestAnnotation("test")
class Parent{

}

class Son extends Parent{
    public static void main(String[] args) {
        TestAnnotation annotation = Son.class.getAnnotation(TestAnnotation.class);
        System.out.println(annotation.value());
    }
}

@Repeatable

  • 用于声明标记的注解为可重复类型注解,可以在同一个地方多次使用

举个栗子:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(BaseAnnotation.class)
public @interface TestAnnotation {

    String value();

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface BaseAnnotation {

    TestAnnotation[] value();

}

@TestAnnotation("test")
@TestAnnotation("test1")
@TestAnnotation("test2")
class Son {
    public static void main(String[] args) {
        BaseAnnotation annotations = Son.class.getAnnotation(BaseAnnotation.class);
        for (TestAnnotation annotation : annotations.value()) {
            System.out.println(annotation.value());
        }
    }
}
上一篇:Spring中@Autowired、@Resource和@Inject注解的使用和区别


下一篇:springboot -- jpa 之分布式主键