java用 @interface Annotation{ } 定义一个注解 @Annotation,一个注解是一个类。自定义注解之前我们先看一下java里已经定义好的一些注解。
@Override,@Deprecated,@SuppressWarnings为常见的3个注解。
@Override
@Override表示子类重写了父类的方法,或者实现了接口的方法。帮助开发者确认子类是否正确的覆盖了父类的方法,若父类中没有此方法,编译器即报错。但是,子类与父类有同样的方法,但子类的方法上没有@Override注解,是不会报错。
@Deprecated
注解@Deprecated,用来表示某个类的属性或方法已经过时,不想别人再用时,在属性和方法
上用@Deprecated修饰,如图:
@SuppressWarnings
@SuppressWarnings是抑制警告的意思。比如新建一个变量,但是没有用,编译器会提示此变量未使用(unused)的警告。如果在方法中,添加了@SuppressWarnings({"unused"})的相关注解,这个警告就不会再提示了。
@SuppressWarnings({"unused"})
public static void main(String[] args) {
int a=10;
}
通过以上常见注解 我们来总结下规律
1.@interface 是声明注解的关键字(就像定义接口时 关键字是 interface)
2.在注解中使用的都是 java.lang.annotation包下的类与接口
3.Annotation 所有注释类型扩展的公共接口。 注意,手动扩展这个接口不限定注释类型。 还要注意,此接口本身并不定义注释类型。
4.在java.lang.annotation包下有已经定义好的注解,我们可以直接拿过来用。
Java提供了4种注解,专门负责新注解的创建,叫做元注解。
分别为
@Target
@Retention
@Documented
@Inherited
@Target
里面有个方法 value() 返回值是ElementType数组
用于描述注解的使用范围,有一个枚举ElementType来指定,具体如下:
CONSTRUCTOR:用于描述构造器
FIELD:用于描述域
LOCAL_VARIABLE:用于描述局部变量
METHOD:用于描述方法
PACKAGE:用于描述包
PARAMETER:用于描述参数
TYPE:用于描述类、接口(包括注解类型) 或enum声明
如下这个Person注解,说明Person注解只能添加到方法上 。
@Target(ElementType.METHOD)
public @interface Person{
}
@Retention
@Retention元注解,表示需要在什么级别保存该注释信息(生命周期)。可选的RetentionPoicy参数包括:
里面有个方法 value() 返回值是RetentionPolicy 保留策略
@Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候;
@Retention(RetentionPolicy.SOURCE )修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中;
@Retention(RetentionPolicy.RUNTIME )修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时,
这里我们常用的是虚拟机运行时所以使用RetentionPolicy.RUNTIME
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Person {
}
@Documented
@Documented:它是一个标记注解,即没有成员的注解,用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化
如果用javadoc生成文档时,想把注解也生成文档,就加这个注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Person {
}
@Inherited
被@Inherited标注的类型是可被继承的,比如一个class被@Inherited标记,那么一个子类继承该class后,则这个annotation将被用于该class的子类。
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Person {
}
下面使用元注解来自定义个注解并使用
类注解
import java.lang.annotation.*;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Documented
public @interface Person {
String value() default "我是人类";
String say() default "我是人类";
String[] organs() default {"耳朵", "眼睛", "鼻子", "嘴"};
}
import java.lang.reflect.Field;
@Person
public class Girl {
@Person("我是女孩")
public String info;
public static void main(String[] args) {
// TODO Auto-generated method stub
method2();
}
public static void method2() {
Class<Girl> c = Girl.class;
//因为注解是在成员字段上,因此需要获得类的所有字段信息
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
//判断这个字段上是否有相应的注解信息(Person.class)
if (field.isAnnotationPresent(Person.class)) {
Person p = field.getAnnotation(Person.class);
System.out.println("信息自述为:"+p.value());
}
}
}
public static void method1() {
Class<Girl> c = Girl.class;
//如果Girl类名上有注解@MyAnnotation修饰,则为true
if(Girl.class.isAnnotationPresent(Person.class))
{
System.out.println("have annotation");
// 若存在就获取注解
Person annotation = (Person) Girl.class.getAnnotation(Person.class);
System.out.println(annotation);
// 数组
String[] arrs = annotation.organs();
for (String arr : arrs) {
System.out.println(arr);
}
// 获取注解方法
System.out.println(annotation.say());
}
}
}