认识注解(一)

  想要了解注解,就要知道注解是什么,有什么作用,怎么声明和使用注解,最后要知道java api中常用的预定义的注解。

一、注解是什么

  注解是为代码提供一些信息,但是注解又不是这段代码的一部分。

  这个概念容易让人想到代理模式,但是两者之间的区别又很明显。静态代理需要为每个类生成一个代理类,很不方便;动态代理是通过反射实现的,只能在运行时起作用。

  而注解既可以在编译时提供警告,如unchecked警告,也可以在运行时实现一些功能。

  这个就有点像做菜的作料一样,你不加也可以吃,加了可以做出更美味的菜肴。可以在做之前加,也可以在做的时候加。

 

二、注解有什么作用

  1.可以用于编译时的检测错误和抑制警告。如@Override注解可以检测重写方法时的错误和@SuppressWarning抑制泛型和使用遗弃的代码所产生的警告。

  2.生成文档,如注释文档和xml文件。如@Documented注解。

  3.用于运行时。但是运行时注解是在运行时使用反射实现功能,所以大量使用运行时注解时,会影响程序的性能。

 

三、如何声明一个注解

  声明一个注解和声明一个接口非常相似,下面定义了一个简单的注解Test,只有一个元素name。看到声明一个注解和区别是在interface关键字前面加一个@符号。第二个区别是可以在元素后面加默认值。

@Target(ElementType.METHOD)
public
@interface Test{ String name() default ""; }

   注解元素的类型只能用限定的几种类型——所有基本类型、String、Class、enum、Annotation和以上类型的数组。如果使用其它类型,编译器就会报错。

 

四、如何使用注解

  1.在使用注解前一定要了解@Target元注解,因为它的取值规定了注解可以在什么地方使用。如上面的@Test注解中@Target注解的取值为ElementType.METHOD,就只能在方法上使用。

   如果想要在类上使用该注解,就需要取值为ElementType.TYPE。

  2.使用注解时,所有的元素都要取值,要么在使用的时候给元素赋值,要么在声明的时候定义默认值。

  3.当元素的名称为value时,可以省略名称。当所有元素都取默认值时,可以省略括号。

  4.一个注解的元素可以取多个值,取多个值时用大括号包含起来,如@SuppressWarnings({"unchecked", "deprecation"})。但是不能将一个注解多次使用在一个地方,如果想多次使用,则需要声明该注解为@Repeatable。

@Target(ElementType.METHOD)
public @interface Test1{
  String name() default "";
  int value() default 0;    
}

public class Demo{

  @Test1(value=1, name="小明")  
  public void f() {}  

  @Test1(2)
  public void h(){}

 @Test1
 public void k() {}
}

 

五、java api中预定义的一些注解

  1.元注解:专门用于注解其他注解的注解

  (1)@Target:声明注解用于什么地方。取值为枚举类型ElementType中的值。

    1)ElementType.TYPE:注解可以注解在类、接口(包括注解类型)和enum的声明上。

    2)ElementType.ANNOTATION_TYPE:注解可以用于注解的声明上。

    3)ElementType.CONSTRUCTOR:注解可以用于构造器声明上。

    4)ElementType.METHOD:注解可以用于方法声明上。

    5)ElementType.PARAMETER:注解可以用于参数声明上。

    6)ElementType.LOCAL_VARIABLE:注解可以用于局部变量的声明上。

    7)ElementType.FIELD:注解可以用于域的声明上。

    8)ElementType.PACKAGE:注解可以用于包的声明上。

  (2)@Retention:声明需要在什么级别上保存注解信息。取值为枚举类型RetentionPolicy中的常量值。

    1)Retention.SOURCE:源码级别,注解将被编译器丢弃。

    2)Retention.CLASS:注解在class文件中可以使用,但是会被VM丢弃。

    3)Retention.RUNTIME:虚拟机在运行期将保留注解,此时可以通过反射机制读取注解中的信息并进行相关操作。

  (3)@Documented:将此注解包含javadoc中。

  (4)@Inherited:允许子类继承父类中的注解。当用户查询子类的注解且子类没有生命注解,此时会查询父类中的注解。

  (5)@Repeatable:声明注解可以在同一个声明的地方重复多次使用,该注解是在java8中引进的。

  2.java内置的标准注解

  (1)@Deprecated:标注代码已经被遗弃了,不推荐被使用。在使用@Deprecated注解时,同时应该在注释中使用@deprecated说明被遗弃的原因以及推荐使用什么作为替代。

      如果使用被该注解标记的代码,则编译器会产生警告信息。

  (2)@Override:用于子类方法上,表示该方法是重写父类的方法。如果该方法签名和父类方法不同,则编译器会报错。

  (3)@SuppressWarning:关闭编译器的警告信息。

    1)取值为unchecked:关闭泛型产生的类型检查警告。

    2)取值为deprecation:关闭使用已经被遗弃的代码产生的警告。

  (4)@FunctionalInterface:表示声明的接口是功能性接口。

  (5)@SafeVarargs:用于方法和构造器时,表示不存在对参数不安全的操作。改标签同时也会关闭unchecked警告。

posted @ 2019-09-04 22:32  qee  阅读(250)  评论(0编辑  收藏  举报