您的位置:首页 > 编程语言 > Java开发

Java 注解

2016-05-14 22:57 363 查看

1. 简介

从JDK5开始,Java开始了对元数据(MetaData)的支持,也就是Annotation(注解),这些标记可以在编译、类加载、运行时被读取。注解可以修饰包,类,构造器,方法,成员变量,参数,局部变量。为了使注解起作用,必须使用APT(注解处理工具)来访问和处理。

2. 基本注解

@Override 强制一个子类必须重写父类的方法,保证父类要包含一个被该方法重写的方法,否则会编译出错

public class Fruit {
public void info() {
System.out.println("水果");
}
}

class Apple extends Fruit {
//只能修饰方法
@Override
public void info() {
System.out.println("苹果");
}
}


@Deprecated表示某个程序元素(类,方法,接口)已过时,当使用这些元素时,编译器会给出警告

@SuppressWarnings 表示被该Annotation修饰的元素取消显示指定的编译器警告,@SuppressWarnings会一直作用于该元素的所有子元素。

@SuppressWarnings(value="unchecked")
public static void main(String[] args) {
List<String> list = new ArrayList();
//会提示Unchecked Assignment
}


@SafeVarargs 抑制引发警告(修饰方法或构造器)

//堆污染:当把一个不带泛型的对象赋给一个带泛型的变量,就可能会发生堆污染
List l = new ArrayList<Number>();
List<String> ls = l;       // unchecked warning
l.add(0, new Integer(42)); // another unchecked warning
String s = ls.get(0);      // ClassCastException is thrown
/*
堆污染发生在静态类型为List<Number>的List对象l被分配给另一个具有不同静态类型List<String>的List对象ls时。由于类型擦除的缘故,类型List<Number> 和 List<String>都会变为List。这样,编译器允许对象l以原始类型List的方式被分配给对象ls。
*/


@FunctionalInterface 如果接口中只有一个抽象方法(可以包含多个默认访问或static方法),该接口就是函数式接口

@FunctionalInterface
public interface FunInterface {

static void foo() {
System.out.println("foo方法");
}

default void bar() {
System.out.println("bar方法");
}
void test();
}


3. 元注解

用来修饰注解

@Retention 用来指定被修饰的注解保留多长时间

//RetentionPolicy.CLASS 把注解记录在class文件中
//RetentionPolicy.RUNTIME 记录在class文件中,并且可以通过反射来获取注解信息
//RetentionPolicy.SOURCE 只保留在源代码中,编译器直接丢掉

@Retention(value=RetentionPolicy.RUNTIME)
public @interface Testable {

}


@Target 用于指定被修饰的注解能用于修饰哪些程序单元

//ElementType.ANNOTATION_TYPE 只能修饰注解
//ElementType.CONSTRUCTOR 只能修饰构造器
//ElementType.FIELD 只能修饰成员变量
//ElementType.METHOD 只能修饰方法
//ElementType.TYPE 可以修饰类,接口(包括注解类型)或枚举


@Documented 用于指定被该注解修饰的注解将被javadoc工具提取成文档

@Inherited 指定被该注解修饰的注解具有继承性

4. 自定义注解

//在默认情况下,注解可修饰任何元素,包括类,接口,方法
public @interface Test {

}

//注解继承了Annotation接口
public @interface MyTag {
//注解的成员变量
String name(); // String name() default "AA";
int age();     // int age() default 0;
}


5. 提取注解信息

通过反射来获取注解信息,java.lang.reflect包下的AnnotatedElement接口,该接口代表程序中可以接受注解的元素,其中有Class, Constructor, Field, Method等

Annotation[] arrays = Class.forName("Test").getMethod("info").getAnnotations();
for(Annotation an : arrays) {
System.out.println(an);
}


6. 重复注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(FkTags.class)
public @interface FkTag {
String name() default "AA";
int age();
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FkTags {
FkTag[] value();
}

@FkTag(name="FF", age=4)
@FkTag(age=8)
public class FkTest {

public static void main(String[] args) {
Class<FkTest> clazz = FkTest.class;
FkTag[] tags = clazz.getDeclaredAnnotationsByType(FkTag.class);
for(FkTag tag : tags) {
System.out.println(tag.name() + " -> " + tag.age());
}

FkTags container = clazz.getDeclaredAnnotation(FkTags.class);
System.out.println(container);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: