java中的Annotation(注解)ITeye - 千亿集团

java中的Annotation(注解)ITeye

2019-01-13 13:11:11 | 作者: 昆雄 | 标签: 注解,类型,成员 | 浏览: 1059

Annotation(注释) 概述
从 JDK 5.0 开端, Java 添加了对元数据(MetaData) 的支撑, 也就是 Annotation(注释)
Annotation 其实就是代码里的特别符号, 这些符号能够在编译, 类加载, 运转时被读取, 并履行相应的处理. 经过运用 Annotation, 程序员能够在不改动原有逻辑的情况下, 在源文件中嵌入一些弥补信息.
Annotation 能够像润饰符相同被运用, 可用于润饰包,类, 结构器, 办法, 成员变量, 参数, 局部变量的声明, 这些信息被保存在 Annotation 的 “name=value” 对中.
Annotation 能被用来为程序元素(类, 办法, 成员变量等) 设置元数据

根本的 Annotation
运用 Annotation 时要在其前面添加 @ 符号, 并把该 Annotation 当成一个润饰符运用. 用于润饰它支撑的程序元素
三个根本的 Annotation:
@Override: 束缚重写父类办法, 该注释只能用于办法
@Deprecated: 用于表明某个程序元素(类, 办法等)已过期
@SuppressWarnings: 按捺编译器正告.

自界说 Annotation
界说新的 Annotation 类型运用 @interface 关键字
Annotation 的成员变量在 Annotation 界说中以无参数办法的方式来声明. 其办法名和返回值界说了该成员的姓名和类型.
能够在界说 Annotation 的成员变量时为其指定初始值, 指定成员变量的初始值可运用 default 关键字
没有成员界说的 Annotation 称为符号; 包含成员变量的 Annotation 称为元数据 Annotation

提取 Annotation 信息
JDK 5.0 在 java.lang.reflect 包下新增了 AnnotatedElement 接口, 该接口代表程序中能够承受注释的程序元素
当一个 Annotation 类型被界说为运转时 Annotation 后, 该注释才是运转时可见, 当 class 文件被载入时保存在 class 文件中的 Annotation 才会被虚拟机读取
程序能够调用 AnnotationElement 目标的如下办法来拜访 Annotation 信息

JDK 的元 Annotation
JDK 的元 Annotation 用于润饰其他 Annotation 界说
@Retention: 只能用于润饰一个 Annotation 界说, 用于指定该 Annotation 能够保存多长时刻, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 运用 @Rentention 时有必要为该 value 成员变量指定值:
RetentionPolicy.CLASS: 编译器将把注释记录在 class 文件中. 当运转 Java 程序时, JVM 不会保存注释. 这是默许值
RetentionPolicy.RUNTIME:编译器将把注释记录在 class 文件中. 当运转 Java 程序时, JVM 会保存注释. 程序能够经过反射获取该注释
RetentionPolicy.SOURCE: 编译器直接丢掉这种战略的注释

JDK 的元 Annotation 2
@Target: 用于润饰 Annotation 界说, 用于指定被润饰的 Annotation 能用于润饰哪些程序元素. @Target 也包含一个名为 value 的成员变量.
@Documented: 用于指定被该元 Annotation 润饰的 Annotation 类将被 javadoc 东西提取成文档.
@Inherited: 被它润饰的 Annotation 将具有承继性.假如某个类运用了被 @Inherited 润饰的 Annotation, 则其子类将主动具有该注释

例如:
@Target(ElementType.TYPE)
public @interface Table {
  /**
  * 数据表称号注解,默许值为类称号
  * @return
  */
  public String tableName() default "className";
}
@Target(ElementType.FIELD)
public @interface NoDBColumn {
}
注解Table 能够用于注解类、接口(包含注解类型) 或enum声明,而注解NoDBColumn仅可用于注解类的成员变量。

@Retention:

@Retention界说了该Annotation被保存的时刻长短:某些Annotation仅出现在源代码中,而被编译器丢掉;而另一些却被编译在class文件中;编译在class文件中的Annotation或许会被虚拟机疏忽,而另一些在class被装载时将被读取(请留意并不影响class的履行,由于Annotation与class在运用上是被别离的)。运用这个meta-Annotation能够对 Annotation的“生命周期”束缚。

效果:表明需求在什么等级保存该注释信息,用于描绘注解的生命周期(即:被描绘的注解在什么规模内有用)

取值(RetentionPoicy)有:

1.SOURCE:在源文件中有用(即源文件保存)
2.CLASS:在class文件中有用(即class保存)
3.RUNTIME:在运转时有用(即运转时保存)

Retention meta-annotation类型有仅有的value作为成员,它的取值来自java.lang.annotation.RetentionPolicy的枚举类型值。详细实例如下:

仿制代码
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
  public String name() default "fieldName";
  public String setFuncName() default "setField";
  public String getFuncName() default "getField";
  public boolean defaultDBValue() default false;
}
仿制代码
Column注解的的RetentionPolicy的特点值是RUTIME,这样注解处理器能够经过反射,获取到该注解的特点值,然后去做一些运转时的逻辑处理

@Documented:

@Documented用于描绘其它类型的annotation应该被作为被标示的程序成员的公共API,因而能够被例如javadoc此类的东西文档化。Documented是一个符号注解,没有成员。

仿制代码
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
  public String name() default "fieldName";
  public String setFuncName() default "setField";
  public String getFuncName() default "getField";
  public boolean defaultDBValue() default false;
}
仿制代码
@Inherited:

@Inherited 元注解是一个符号注解,@Inherited论述了某个被标示的类型是被承继的。假如一个运用了@Inherited润饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

留意:@Inherited annotation类型是被标示过的class的子类所承继。类并不从它所完结的接口承继annotation,办法并不从它所重载的办法承继annotation。

当@Inherited annotation类型标示的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种承继性。假如咱们运用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码查看将打开作业:查看class和其父类,直到发现指定的annotation类型被发现,或许抵达类承继结构的顶层。

实例代码:
/**
*
* @author peida
*
*/
@Inherited
public @interface Greeting {
  public enum FontColor{ BULE,RED,GREEN};
  String name();
  FontColor fontColor() default FontColor.GREEN;
}
仿制代码
自界说注解:

运用@interface自界说注解时,主动承继了java.lang.annotation.Annotation接口,由编译程序主动完结其他细节。在界说注解时,不能承继其他的注解或接口。@interface用来声明一个注解,其间的每一个办法实际上是声明晰一个装备参数。办法的称号就是参数的称号,返回值类型就是参数的类型(返回值类型只能是根本类型、Class、String、enum)。能够经过default来声明参数的默许值。

界说注解格局:
public @interface 注解名 {界说体}

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

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 peida
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
  String value() default "";
}

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 peida
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {
  /**
  * 色彩枚举
  * @author peida
  *
  */
  public enum Color{ BULE,RED,GREEN};
 
  /**
  * 色彩特点
  * @return
  */
  Color fruitColor() default Color.GREEN;

}
仿制代码
仿制代码
package annotation;

import annotation.FruitColor.Color;

public class Apple {
 
  @FruitName("Apple")
  private String appleName;
 
  @FruitColor(fruitColor=Color.RED)
  private String appleColor;
 
 
 
 
  public void setAppleColor(String appleColor) {
  this.appleColor = appleColor;
  }
  public String getAppleColor() {
  return appleColor;
  }
  public void setAppleName(String appleName) {
  this.appleName = appleName;
  }
  public String getAppleName() {
  return appleName;
  } 
  public void displayName(){
  System.out.println("生果的姓名是:苹果");
  }
}
仿制代码
注解元素的默许值:

注解元素有必要有断定的值,要么在界说注解的默许值中指定,要么在运用注解时指定,非根本类型的注解元素的值不可为null。因而, 运用空字符串或0作为默许值是一种常用的做法。这个束缚使得处理器很难体现一个元素的存在或缺失的状况,由于每个注解的声明中,一切元素都存在,而且都具有相应的值,为了绕开这个束缚,咱们只能界说一些特别的值,例如空字符串或许负数,一次表明某个元素不存在,在界说注解时,这已经成为一个习惯用法。例如:

仿制代码
1 package annotation;
2
3 import java.lang.annotation.Documented;
4 import java.lang.annotation.ElementType;
5 import java.lang.annotation.Retention;
6 import java.lang.annotation.RetentionPolicy;
7 import java.lang.annotation.Target;
8
9 /**
10  * 生果供应者注解
11  * @author peida
12  *
13  */
14 @Target(ElementType.FIELD)
15 @Retention(RetentionPolicy.RUNTIME)
16 @Documented
17 public @interface FruitProvider {
18  /**
19  * 供货商编号
20  * @return
21  */
22  public int id() default -1;
23 
24  /**
25  * 供货商称号
26  * @return
27  */
28  public String name() default "";
29 
30  /**
31  * 供货商地址
32  * @return
33  */
34  public String address() default "";
35 }
仿制代码


界说了注解,并在需求的时分给相关类,类特点加上注解信息,假如没有响应的注解信息处理流程,注解能够说是没有实用价值。怎么让注解真真的发挥效果,首要就在于注解处理办法,下一步咱们将学习注解信息的获取和处理!
版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表千亿集团立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章