概述
-
1.注解Annotation是一种引用数据类型。编译之后也是生成class文件
-
2.自定义注解:
[修饰符列表] @interface 注解类型名{} -
3.注解怎么使用,用在什么地方:
第一:注解使用的语法格式:@注解类型名
第二:注解可以出现在类上、属性上、方法上、变量上等,注解还可以出现在注解上
示例程序:
//MyAnnotation 注解类型
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
/**
* 在注解中可以定义属性,以下是MyAnnotation的name属性
* 看着像一个方法,实际上是属性
*
* 属性的类型可以是:
* 八种基本数据类型、String、class,它们的数组类型也可以
*/
String name();
int age() default 22; //给属性指定默认值
//如果属性名是value,且只有一个属性的话,则该属性名可以省略
String value();
}
public enum Season {
SPRING,SUMMER,AUTUNDO,WINTER
}
@MyAnnotation(name = "lisi", age = 12, value = "ee",season = {Season.SPRING,Season.SUMMER})
public class AnnotationTest01{
//如果数组中只有一个元素,则大括号可以省略
@MyAnnotation(name = "zhangsan",value = "ee",season = Season.SPRING)
public void doSome(){
}
}
元注解
-
Target:
用来标注”被标注的注解“可以出现在那些位置上
@Target(ElementType.METHOD) : 表示”被标注的注解“只能出现在方法上 -
Retention:
用来”被标注的注解“最终保存在哪里
@Retention(RetentionPolicy.SOURCE) :表示该注解被保存在java源文件中
@Retention(RetentionPolicy.CLASS):表示该注解被保存在class文件中
@Retention(RetentionPolicy.RUNTIME):表示该注解被保存在class文件中,并且可以被反射机制读取
在此基础上看看 @Override 的源码
@Target(ElementType.METHOD) //只能出现在方法上
@Retention(RetentionPolicy.SOURCE) //表示该注解被保存在源文件中
public @interface Override {}
- 是给编译器参考的,和运行阶段没有关系
- 如果给方法加上了它,编译器会自动检测是否正确的重写了父类的方法
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {}
- 表示被标注的已过时,不推荐使用
public class AnnotationTest03 {
public static void main(String[] args) {
T.doSome(); //doSome有横线
}
}
class T{
@Deprecated
public static void doSome(){
}
}
通过反射机制获取注解
- 该注解必须被保存在class文件中,并且可以被反射机制读取
示例程序:
public class RefledtAnnotationTest {
public static void main(String[] args) throws Exception {
Class c = Class.forName("T");
//如果c类有MyAnnotation这个注解,则返回true
if(c.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation myAnnotation = (MyAnnotation)c.getAnnotation(MyAnnotation.class);
//专门用来获取属性名为"value"的值
String value = myAnnotation.value();
System.out.println(value);
} else {
System.out.println(false);
}
//获取方法上完整属性
Method doSomeMethod = c.getDeclaredMethod("doSome");
if(doSomeMethod.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation myAnnotation = doSomeMethod.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.name());
System.out.println(myAnnotation.age());
System.out.println(myAnnotation.value());
}
}
}
注解的使用实例
编写一个注解Id,用来修饰类,如果该类没有定义int id属性,就抛出异常
代码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
}
public class HasNotIdPropertyException extends RuntimeException{
public HasNotIdPropertyException(){
}
public HasNotIdPropertyException(String s){
super(s);
}
}
@Id
public class User {
int id;
String name;
int age;
}
public class Test {
public static void main(String[] args) throws Exception {
Class userClass = Class.forName("example.User");
if(userClass.isAnnotationPresent(Id.class)){
//获取类的属性
Field[] fields = userClass.getDeclaredFields();
boolean flag = false;
for(Field f : fields){
if("id".equals(f.getName()) && "int".equals(f.getType().getSimpleName())){
flag = true;
break;
}
}
if(!flag){
throw new HasNotIdPropertyException("没有定义int id属性");
}
}
}
}