注釈付きJAVAの原則

自然の注釈

「Java.lang.annotation.Annotation」インターフェース記述するので、多くの言葉がある「ノート」。

すべての注釈型によって拡張される共通のインタフェース

すべての注釈型が共通のインタフェースから継承されている(注釈)

少し抽象この文は、しかし、彼らは、注釈の性質を言います。私たちは、JDKビルトイン定義された注釈を見て:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { } 

ノートは、実際には、それが本質的である@Overrideこれは定義です:

public interface Override extends Annotation{ } 

はい、性質が継承された注釈インターフェイス注釈インタフェースです。この点で、あなたは結果を得るだろう、アノテーションクラスのいずれかをコンパイルするために行くことができます。

それはそれもコメントしないかもしれないようなコードが解決しない場合は、正確な意味でのノートでは、それは、特別なコメントです。

クラスまたはアノテーションを解析するための方法は、多くの場合、二つの形式、スキャンの直接編集、および反射の実行を持っています。我々はパーサジェネレータをスキャンすると、クラスを参照したりする方法は、いくつかの注意事項が検出されたバイトコードにコンパイルされたJavaコードを処理するように変更されているが、反映していると言うだろうどのようなこと、それはこれらのアノテーションになりますいくつかの処理。

典型的なコメント@Overrideは、コンパイラが方法が@Overrideアノテーションで変更された検出すると、コンパイラがチェックする現在の方法は、比較的親クラスである本当の親クラスのメソッドシグネチャを、オーバーライドするかどうか、です同様の方法で署名するかどうか。

この場合は、このような組み込みのJDKいくつかの注意事項として、唯一のクラスコンパイラがすでに精通しているそれらの注釈に適用され、カスタムコンパイラに注釈を付けますが、もちろん、この注釈役割を認識していない、に対処する方法を知りませんでしたが、多くの場合、バイトコードファイルにコンパイルするかどうかを選択して、注釈に従い、何よりもスコープます。

元のメモ

「メタ注釈は」など、通常のアノテーションの定義に、注釈付きのノートを修正するために使用されます。

@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { } 

これは@Overrideアノテーションの私達の定義である、あなたは、リテンション2つのノート@、ターゲット@それらを見ることができ、私たちは「メタアノテーション」と呼ぶもので、「メタアノテーションは、」一般的注釈情報のライフサイクルと目標の役割を指定するために使用されます。

JAVAはいくつかの「メタアノテーションを」持っています:

  • @Target:ターゲット注釈の役割
  • @Retention:ライフサイクルの注意事項
  • @Documented:注解是否应当被包含在 JavaDoc 文档中
  • @Inherited:是否允许子类继承该注解

其中,@Target 用于指明被修饰的注解最终可以作用的目标是谁,也就是指明,你的注解到底是用来修饰方法的?修饰类的?还是用来修饰字段属性的。

@Target 的定义如下:

 
image

我们可以通过以下的方式来为这个 value 传值:

@Target(value = {ElementType.FIELD}) 

被这个 @Target 注解修饰的注解将只能作用在成员字段上,不能用于修饰方法或者类。其中,ElementType 是一个枚举类型,有以下一些值:

  • ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上
  • ElementType.FIELD:允许作用在属性字段上
  • ElementType.METHOD:允许作用在方法上
  • ElementType.PARAMETER:允许作用在方法参数上
  • ElementType.CONSTRUCTOR:允许作用在构造器上
  • ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上
  • ElementType.ANNOTATION_TYPE:允许作用在注解上
  • ElementType.PACKAGE:允许作用在包上

 

@Retention 用于指明当前注解的生命周期,它的基本定义如下:

 
image

同样的,它也有一个 value 属性:

@Retention(value = RetentionPolicy.RUNTIME

这里的 RetentionPolicy 依然是一个枚举类型,它有以下几个枚举值可取:

  • RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件
  • RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件
  • RetentionPolicy.RUNTIME:永久保存,可以反射获取

@Retention 注解指定了被修饰的注解的生命周期,一种是只能在编译期可见,编译后会被丢弃,一种会被编译器编译进 class 文件中,无论是类或是方法,乃至字段,他们都是有属性表的,而 JAVA 虚拟机也定义了几种注解属性表用于存储注解信息,但是这种可见性不能带到方法区,类加载时会予以丢弃,最后一种则是永久存在的可见性。

剩下两种类型的注解我们日常用的不多,也比较简单,这里不再详细的进行介绍了,你只需要知道他们各自的作用即可。@Documented 注解修饰的注解,当我们执行 JavaDoc 文档打包时会被保存进 doc 文档,反之将在打包时丢弃。@Inherited 注解修饰的注解是具有可继承性的,也就说我们的注解修饰了一个类,而该类的子类将自动继承父类的该注解。

 

 

JAVA 的内置三大注解

除了上述四种元注解外,JDK 还为我们预定义了另外三种注解,它们是:

  • @Override
  • @Deprecated
  • @SuppressWarnings

@Override 注解想必是大家很熟悉的了,它的定义如下:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { } 

它没有任何的属性,所以并不能存储任何其他信息。它只能作用于方法之上,编译结束后将被丢弃。

所以你看,它就是一种典型的『标记式注解』,仅被编译器可知,编译器在对 java 文件进行编译成字节码的过程中,一旦检测到某个方法上被修饰了该注解,就会去匹对父类中是否具有一个同样方法签名的函数,如果不是,自然不能通过编译。

@Deprecated 的基本定义如下:

 
image

依然是一种『标记式注解』,永久存在,可以修饰所有的类型,作用是,标记当前的类或者方法或者字段等已经不再被推荐使用了,可能下一次的 JDK 版本就会删除。

当然,编译器并不会强制要求你做什么,只是告诉你 JDK 已经不再推荐使用当前的方法或者类了,建议你使用某个替代者。

@SuppressWarnings 主要用来压制 java 的警告,它的基本定义如下:

 
image

它有一个 value 属性需要你主动的传值,这个 value 代表一个什么意思呢,这个 value 代表的就是需要被压制的警告类型。例如:

public static void main(String[] args) { Date date = new Date(2018, 7, 11); } 

这么一段代码,程序启动时编译器会报一个警告。

Warning:(8, 21) java: java.util.Date 中的 Date(int,int,int) 已过时

而如果我们不希望程序启动时,编译器检查代码中过时的方法,就可以使用 @SuppressWarnings 注解并给它的 value 属性传入一个参数值来压制编译器的检查。

@SuppressWarning(value = "deprecated") public static void main(String[] args) { Date date = new Date(2018, 7, 11); } 

这样你就会发现,编译器不再检查 main 方法下是否有过时的方法调用,也就压制了编译器对于这种警告的检查。

当然,JAVA 中还有很多的警告类型,他们都会对应一个字符串,通过设置 value 属性的值即可压制对于这一类警告类型的检查。

自定义注解的相关内容就不再赘述了,比较简单,通过类似以下的语法即可自定义一个注解。

public @interface InnotationName{ } 

当然,自定义注解的时候也可以选择性的使用元注解进行修饰,这样你可以更加具体的指定你的注解的生命周期、作用范围等信息。

 

 

注解的内容

在上面的注解源码中可以看到有的注解中没有任何内容,有的注解的有内容,看似像方法。

注解的内容的语法格式:

数据类型 属性名() default 默认值,数据类型用于描述属性的数据类型,默认值是说当没有给属性赋值时使用默认值,一般String使用空字符串""作为默认值,数组一般使用空数组{ }作为默认值.

下面看一下SpringMVC中的RequestMapping的注解的声明

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";

@AliasFor("path")
String[] value() default {};

@AliasFor("value")
String[] path() default {};

RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}

注解和反射基本API


// 获取某个类型的注解
public <A extends Annotation> A getAnnotation(Class<A> annotationClass);


// 获取所有注解(包括父类中被Inherited修饰的注解)
public Annotation[] getAnnotations();


// 获取声明的注解(但是不包括父类中被Inherited修饰的注解)
public Annotation[] getDeclaredAnnotations();


// 判断某个对象上是否被某个注解进行标注
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

// 获取某个类声明的所有字段
public Field[] getDeclaredFields() throws SecurityException;
// 获取某个方法
public Method getMethod(String name, Class<?>... parameterTypes);

使用自定义注解可以在切面编程中使用,处理异常等

おすすめ

転載: www.cnblogs.com/duan2/p/11704564.html