再论Java注解

一、什么是注解?

注解其实就是代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相对应的处理

二、为什么要用注解开发?

传统的方式是,通过配置文件(xml文件 )来告诉类是如何运行的,使用注解开发后,通过注解告诉类是如何运行

三、元注解(注解的注解)

  • @Target:注解作用目标(即:被描述的注解可以用在什么地方)

    • @Target(ElementType.TYPE)——接口、类、枚举、注解
    • @Target(ElementType.FIELD)——字段、枚举的常量
    • @Target(ElementType.METHOD)——方法
    • @Target(ElementType.PARAMETER)——方法参数
    • @Target(ElementType.CONSTRUCTOR) ——构造函数
    • @Target(ElementType.LOCAL_VARIABLE)——局部变量
    • @Target(ElementType.ANNOTATION_TYPE)——注解
    • @Target(ElementType.PACKAGE)——包
  • @Retention:注解的保留位置,用于描述注解的生命周期(SOURCE->CLASS -> RUNTIME

    • RetentionPolicy.SOURCE:这种类型的Annotations只在源代码级别保留,编译时就会被忽略,在class字节码文件中不包含
    • RetentionPolicy.CLASS:这种类型的Annotations编译时被保留,默认的保留策略,在class文件中存在,但JVM将会忽略,运行时无法获得
    • RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。
  • @Document:说明该注解将被包含在javadoc

  • @Inherited:是一个标识,用来修饰注解

    • 作用:如果一个类用上了@Inherited修饰的注解,那么其子类也会继承这个注解

      注意:

      • 接口用上个@Inherited修饰的注解,其实现类不会继承这个注解
      • 父类的方法用了@Inherited修饰的注解,子类也不会继承这个注解

四、JDK基本注解

4.1 @Override

重写注解

@Overried是告诉编译器要检查该方法是实现父类的…可以帮我们避免一些低级的错误…

比如,我们在实现equals()方法的时候,把euqals()打错了,那么编译器就会发现该方法并不是实现父类的,与注解@Override冲突,于是就会给予错误

4.2 @Deprecated

过时注解

在Java迭代中,觉得某些方法设计不好,而为了兼容老版本,不能直接抛弃掉,于是加上注解表明过时的,不建议再用

Date对象中的toLocalString()就被设计为过时的

@Deprecated
public String toLocaleString() {
    DateFormat formatter = DateFormat.getDateTimeInstance();
    return formatter.format(this);
}

4.3 SuppressWarnings

镇压警告注解

该注解可以抑制编译器给我们提示的安全警告

4.4 @SafeVarargs

Java7 “堆污染”警告注解

在声明具有模糊类型(比如:泛型)的可变参数的构造函数或方法时,Java编译器会报unchecked警告。鉴于这些情况,如果程序员断定声明的构造函数和方法的主体不会对其varargs参数执行潜在的不安全的操作,可使用@SafeVarargs进行标记,这样的话,Java编译器就不会报unchecked警告

4.5 @FunctionalInterface

@FunctionalInterface函数式接口注解

该注解指定该接口是函数式接口

五、自定义注解

需求:给方法或类注入信息

5.1 标记Annotation

没有任何成员变量的注解称作为标记注解,@Overried就是一个标记注解

public @interface MyAnnotation {
}

5.2 元数据Annotation

注解是可以带成员变量的,定义带成员变量的注解叫做元数据Annotation

在注解中定义成员变量,语法类似于声明方法一样….

public @interface MyAnnotation {
    String username();
    int age();
}

5.3 使用自定义注解

5.3.1 基本使用

给add方法注入username和age这 两个参数

//注解拥有什么属性,在修饰的时候就要给出相对应的值
@MyAnnotation(username = "xiaoming", age = 20)
public void add(String username, int age) {
}

5.3.2 默认值

注解声明属性的时候给出默认值,这样我们就可以在使用注解的时候省略掉属性赋值

public @interface MyAnnotation {
    String username() default "xiaoming";
    int age() default 20;
}

使用注解

@MyAnnotation()
public void add(String username, int age) {
}

5.3.3 注解属性为value

有一种特殊的情况,如果注解上只有一个属性,并且属性的名称为value,那么在使用的时候,我们可以不写value,直接赋值给它就行

public @interface MyAnnotation2 {
   String value();
}

使用注解

@MyAnnotation2("zhongfucheng")
public void find(String id) {
}

六、总结

  1. 注入对象的步骤:得到想要注入的对象属性,通过属性得到注解的信息,通过属性的写方法将注解的信息注入到对象上,最后将对象赋给类

  2. 注解其实就是两个作用:

    1. 让编译器检查代码
    2. 将数据注入到方法、成员变量、类上
  3. 在JDK中注解分为

    1. 元Annotaion:在annotaion包下,常用于修饰其他的Annotation定义
    2. 基本Annotation:在lang包下,用于常用于标记该方法,抑制编译器警告等
posted @ 2021-11-17 19:45  对弈  阅读(42)  评论(0编辑  收藏  举报