一.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