了解Java注解

此文将介绍注解的三个方面:


1. Java内建的注解

Java有三个内建的注解

  1. @Override - 当重写父类方法的时候,我们使用这个注解来通知编译器我们正在重写这个方法。当父类的这个方法被移除或改变的时候,编译器会提示一个错误信息。
  2. @Deprecated - 这个注解用来告诉编译器某个方法已经被废弃。当某个地方调用此方法,编译器会提示该方法已被废弃。
  3. @SuppressWarnings - 此注解用来告诉编译器忽略掉某个(些)警告。
@Deprecated
public static void oldMethod(){    
      System.out.println("old method. Do not use it.");
}

public static void genericsTest() throws FileNotFoundException{    
      List list = new ArrayList<>();    
      list.add("abc");    
      oldMethod();
}

比如上面这两个方法,oldMethod()方法被@Deprecated注解了。所以编译器中在genericsTest()方法里面调用oldMethod()时,代码会出现如下的形态以提示该方法已被废弃:

oldMethod()

而list.add(“abc”)代码处编译器会提示:Unchecked call to add(E) as a member of the raw type java.util.List 这个警告的出现是因为此处list未指定数据类型。如果想忽略掉此警告,可以在genericsTest()方法上面添加注解:
@SuppressWarnings("unchecked")

SuppressWarnings注解可以传入多个值,下面列举一些常见的:

作用
all所有警告
boxingboxing/unboxing操作相关的警告
cast类型转换操作相关的警告
dep-ann被废弃的注解相关的警告
deprecation弃用相关的警告
fallthroughswitch语句中丢失break相关的警告
finallyfinally块中不返回相关的警告
hiding本地变量隐藏父类变量相关的警告
incomplete-switchswtich语句中入口缺失相关的警告(枚举变量)
nullnull值分析相关的警告
rawtypes在类的参数中使用未指定类型的泛型时相关的警告
restriction使用了不推荐的或者禁止的引用时的警告
serial在serializable类中缺失serialVersionUID时的警告
static-access用错误的方式访问static 值/方法 时的警告
synthetic-access来自内部类未经优化的访问相关的警告
unchecked未经检查的操作相关的警告
unqualified-field-access不合格地访问字段相关的警告
unused有未使用的代码相关的警告


2. 自定义注解

先看下面的一个自定义注解:


@Documented 
@Target(ElementType.METHOD) 
@Inherited 
@Retention(RetentionPolicy.RUNTIME) 
public @interface MethodInfo{ 
        String author() default "xiaoqiang"; 
        String date(); 
        int revision() default 1; 
        String comments() default ""; 
}

几个值得注意的地方:

  • 定义一个注解和定义一个接口类似,不过关键字是 @interface
  • 注解的方法不能有参数
  • 注解方法的返回值只能是原始数据类型、枚举、Annotation或者这些的数组
  • 注解方法可以有默认值
  • 注解可以有原始注解,原始注解定义了注解的一些属性

Java中有四个原始注解

  1. @Documented: 意味着使用该注解的元素应该被 javadoc和类似工具记录。如果使用Documented注解类型声明,其注解将成为该元素的公共API的一部分。

  2. @Target: 指明该注解的类型,其中一些值有TYPEMETHODCONSTRUCTORFIELD。比如被 @Target(ElementType.METHOD) 标记的注解只能用来注解方法。如果一个注解没有@Target,那么它可以被用来注解任意元素。

  3. @Inherited: 表示自动继承注解类型。 如果用户在类声明上查询该注解类型,并且类声明没有此类型的注解,则将自动查询类的父类以获取注解类型。 此过程将重复直到找到此类型的注解,或者直到查找到Object类。

  4. @Retention: 表示该注解将保留多久。它有三个值 RetentionPolicy.SOURCERetentionPolicy.CLASSRetentionPolicy.RUNTIME。SOURCE表示注解将被编译器丢弃。CLASS表示注解会被编译器记录下来,但会在运行时被丢弃,这是注解的默认状态。RUNTIME表示注解会被编译器记录,并且在运行时仍然被保留,因此它可以被反射。



3. 反射注解

反射注解就是在运行时将注解解析出来。前面已经提到,只有标注了@Retention(RetentionPolicy.RUNTIME) 的注解才能保留到运行时,因此反射也只能运用在此类注解上。

我们将在 2 中自定义的注解用到如下的方法上:

public final class Gas95{        
      @MethodInfo(comments = "gas95 is good", date = "Jan 24 2019")
      public void printGasInfo( boolean includeCompany,  String test){       
            //do anything    
      }   
}

接着可以通过反射来解析printGasInfo方法的注解,具体代码如下:

//通过反射获取方法printGasInfo
Method method = Gas95.class.getMethod("printGasInfo", boolean.class, String.class);
//获取方法的MethodInfo注解
MethodInfo annotation = method.getAnnotation(MethodInfo.class);
//打印注解的值
System.out.println("author = " + annotation.author()       
            + "\ndate = " + annotation.date()        
            + "\nversion = " + annotation.version()        
            + "\ncomments = " + annotation.comments());

打印的结果如下:

author = xiaoqiang
date = Jan 24 2019
version = 1
comments = gas95 is pretty good

可以看到,commentsdate的值就是我们在使用注解时传入的值,而authorversion,由于使用时没有赋值,因此都是默认值。对于没有默认值的注解方法,比如这里的date,在使用时必须赋值。



以上是注解的一些常见用法,欢迎交流讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值