JAVA注解

313 阅读6分钟

1.注解的定义

官方定义

Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。

1.1元注解

元注解定义

元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解

  1. @Target,
  2. @Retention
  3. @Documented
  4. @Inherited

对于注解的跟人理解。举个不恰当的比喻,注解就好比现实的标签。比如高富帅标签,那么元注解就是具体来注解规范这个高富帅标签的内容。比如通过元注解规定这个高富帅标签只能给人使用,动物则不行。比如这个标签只对成年人有效,小孩子会自动忽略等。

1.2元注解具体说明

1.2.1 @Retention

Retention 的英文意为保留期的意思。当 @Retention 应用到一个注解上的时候,它解释说明了这 个注解的的存活时间。 它的取值如下:

  • RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
  • RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
  • RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。

这3个生命周期分别对应于:Java源文件(.java文件) ---> .class文件 ---> 内存中的字节码

由于不同注解使用的时间是不同的,比如动态注解是在运行时获取注解进行相应操作的,静态注解则在编译的时候。所以要精细划分注解的保留时间就需要这个元注解。使用如下:

@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}
1.2.2 @Documented

这个元注解肯定是和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去

1.2.3 @Target

@Target 指定了注解运用的地方。就看该标签是运用到类还是说方法还是说其他某些地方。 具体@Target取值有

  • ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
  • ElementType.CONSTRUCTOR 可以给构造方法进行注解
  • ElementType.FIELD 可以给属性进行注解
  • ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
  • ElementType.METHOD 可以给方法进行注解
  • ElementType.PACKAGE 可以给一个包进行注解
  • ElementType.PARAMETER 可以给一个方法内的参数进行注解
  • ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
1.2.4 @Inherited

Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface Test {}


@Test
public class A {}


public class B extends A {}

注解 Test 被 @Inherited 修饰,之后类 A 被 Test 注解,类 B 继承 A,类 B 也拥有 Test 这个注解。

2.预置注解

Java 默认带了一些注解,平时开发的时候其实也已经在默默使用了。

2.1 @Deprecated

该注解用来标记过时的元素,若某个类或者方法或者元素等被标记了,那么别的引用到那处代码的地方会出现划线,进行标示,提醒使用者,这个代码已经过时,使用要慎重。

  @Deprecated
    public void stopPullLoading() {
    
    }

2.2 @Override

 java.lang.Override 是一个marker annotation类型,它被用作标注方法。它说明了被标注的方法重载了父类的方法,起到了断言的作用。如果我们使用了这种annotation在一个没有覆盖父类方法的方法时,java编译器将以一个编译错误来警示。

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

2.3 @SuppressWarnings

此注解能告诉Java编译器关闭对类、方法及成员变量的警告。 SuppressWarning不是一个marker annotation。它有一个类型为String[]的成员,这个成员的值为被禁止的警告名。对于javac编译器来讲,被-Xlint选项有效的警告名也同样对@SuppressWarings有效,同时编译器忽略掉无法识别的警告名。

@SuppressWarnings(value={"unchecked","fallthrough"})  
  
public void lintTrap() { /* sloppy method body omitted */ }  

3.自定义注解

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

注解参数的可支持数据类型:

  1. 所有基本数据类型(int,float,boolean,byte,double,char,long,short)
  2. String类型
  3. Class类型
  4. enum类型
  5. Annotation类型 6.以上所有类型的数组

  Annotation类型里面的参数该怎么设定:   第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;      第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;     第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子FruitName注解就只有一个参数成员。

简单的自定义注解和使用注解实例:

package annotation;  
  
import java.lang.annotation.Documented;  
import java.lang.annotation.ElementType;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;  
import java.lang.annotation.Target;  
  
/** 
 * 水果名称注解 
 * @author wangsheng 
 * 
 */  
@Target(ElementType.FIELD)  
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
public @interface FruitName {  
    String value() default "";  
} 

4.注解的作用

个人开发时注解的作用:

  1. 通过注解标注让系统在编译或者运行时来处理某些重复事件,如View的id绑定,点击事件绑定等
  2. 信息收集,比如被注解的类被收集注册到一个集合,以便于监听处理
  3. 其他一些未使用过的功能(接下来想到补充)

5.运行时注解

一般在运行时反射获取到注解的内容,然后进行相应的操作,比如绑定id等。 参考了解:juejin.cn/post/684490…

6.编译时注解

需要使用到APT,在代码编译阶段根据注解完成相应代码的添加,由于在编译阶段完成了相关工作,所以影响比动态注解小,性能更好。

(留坑接下来写文章填)