一.java注解(Annotation):
jdk5.0中添加了新的特性注解,与接口很类似,但注解也是java的一种类型,注解的作用非常多例如进行编译检查、生成说明文档、代码分析等。
jdk提供的常用注解:
1. @Override:
表示子类要重写父类对应的方法。
例子:
class Father { public void present(){ System.out.println("Father"); } public static void a(){ System.out.println("a"); } } public class Son extends Father { //@Override表示重写父类中的present()方法。 @Override public void present() { super.present(); } /* 静态方法是不能重写的,所以当我们加上@Override时,会提示错误。 @Override public static void a(){ System.out.println("a"); } */ }
表示该方法是不建议使用的。
例子:
public class Test { @Deprecated public void put(){ System.out.println("Test"); } }
public class Test2 { public static void main(String[] args) { Test t = new Test(); //当时用这个方法时就会有警告,表示当前方法是不赞成使用的。 t.put(); } }
该注解表示压制警告。
参数值列表:
deprecation:过时的类或方法警告。
unchecked:执行了未检查的转换时警告。
fallthrough:当Switch程序块直接通往下一种情况而没有Break时的警告。
path:在类路径、源文件路径等中有不存在的路径时的警告。
serial:当在可序列化的类上缺少serialVersionUID定义时的警告。
finally:任何finally子句不能完成时的警告。
all:关于以上所有情况的警告。
例子:
public class Test2 { @SuppressWarnings({ "deprecation" }) public static void main(String[] args) { Test t = new Test(); //当时用这个方法时就会有警告,表示当前方法是不赞成使用的。 t.put(); } }
二.自定义注解:
如何定义注解:
public @interface MyAnnotation { //当我们使用value作为属性名时,我们在对其赋值时可以不指定属性的名称,而直接写上属性就可以了。这种方式只对value单一一个传值时才适用。 //除value以外的属性名,则都需要 name=value 这种赋值方式,明确的指出赋值的对象是谁。 //例如@SuppressWarnings({ "deprecation" }),如此的传值,如果多个值,就需要用花括号括起,每个值之间加逗号。 String value() ; //默认值为hello。 String hello() default "hello"; }
当我们使用@interface关键字定义一个注解时,该注解隐含的继承了java.lang.annotation.Annotation接口,如果我们定义了一个接口,并让接口继承Annotation,那么我们所定义的接口依然还是接口而不是注解,Annotation本身是借口而不是注解。
如何使用自定义注解:
public class Test { @MyAnnotation("a") public void a(){ System.out.println("A"); } @MyAnnotation(value="b",hello="c") public void b(){ System.out.println("B"); } }
二.注解应用:
@Target的使用:
指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。
必需元素摘要 | |
---|---|
ElementType[] |
value |
public abstract ElementType[] value
当定义那种类型则只能对该类型的程序元素上使用该注解:
枚举常量摘要 | |
---|---|
ANNOTATION_TYPE 注释类型声明 |
|
CONSTRUCTOR 构造方法声明 |
|
FIELD 字段声明(包括枚举常量) |
|
LOCAL_VARIABLE 局部变量声明 |
|
METHOD 方法声明 |
|
PACKAGE 包声明 |
|
PARAMETER 参数声明 |
|
TYPE 类、接口(包括注释类型)或枚举声明 |
例子(只能用于方法的注解定义):
注解:
@Target(ElementType.METHOD) public @interface MyAnnotation { }
public class MyTest { @MyAnnotation() public void a(){ System.out.println(" a "); } @MyAnnotation() public void b(){ System.out.println(" b "); } }
当ElementType.METHOD则为专门对方法修饰的注解。如果放于其他位置则会报错。
对于注解如何使用反射:
@Retention
必需元素摘要 | |
---|---|
RetentionPolicy |
value |
public abstract RetentionPolicy value
枚举常量摘要 | |
---|---|
CLASS 编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。 |
|
RUNTIME 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。 |
|
SOURCE 编译器要丢弃的注释。 |
例子:
注解:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { //表示默认值为hello String hello() default "hello"; String world(); }
public class MyTest { @Deprecated @MyAnnotation(world="java") public void output(){ System.out.println("output !"); } }
public class Test { public static void main(String[] args) throws Exception { Class<MyTest> c = MyTest.class; //获取指定的方法 Method method = c.getMethod("output",new Class[]{}); //如果指定类型的注释存在于此元素上,则返回 true,否则返回 false if(method.isAnnotationPresent(MyAnnotation.class)){ //执行output方法 method.invoke(new MyTest(),new Object[]{}); MyAnnotation ma = method.getAnnotation(MyAnnotation.class); //返回字符串 String str = ma.hello(); String str2 = ma.world(); System.out.println(str+" , "+str2); } //获得方法上存在的注解类型 Annotation[] annotations = method.getAnnotations(); for(Annotation annotation : annotations){ System.out.println(annotation.annotationType().getName()); } } }
打印:
output !
hello , java
java.lang.Deprecated
lzr.annotation.MyAnnotation