注解
注解(Annotation)
1、注解是一种引用数据类型,编译之后也是生成xxx.class
文件。
2、语法格式:
/* [修饰符列表] @interface 注解类型名{} */
public @interface MyAnnotation{
}
3、注解的使用
一:注解使用时的语法格式@注解类型名
二:注解可以出现在 类、属性、方法、变量、注解类型上等等。
4、JDK内置的注解java.lang
Deprecated
:不鼓励程序员使用这样的元素,通常因为它很危险或存在更好的选择。
Override
:表示一个方法声明打算重写超类中的另一个方法声明。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override{ }
- 这个注解只能注解方法。
- 这个注解是给编译器参考的,和运行阶段没有关系。
- 标识性注解给编译器做参考。Java 中带有这个注解,编译器就会进行编译检查,如果这个方法不是重写父类的方法则编译器报错。
SuppressWarnings
:指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。
元注解
1、元注解:用来标注“注解类型”的“注解”,称为元注解。
-
Target
:这个元注解用来标注"被标注的注解"可以出现在哪些位置上。@Target(ElementType.METHOD)
:表示被标注的注解只能出现在方法上。 -
Retention
:用来标注“被标注的注解”最终保存在哪里。@Retention(RetentionPolicy.SOURCE)
:表示该注解只被保留在Java 源文件中。(如:@Override在 class 文件找不到,只能在 java 源文件中找到)@Retention(RetentionPolicy.CLASS)
:表示该注解只被保留在 class 文件中。@Retention(RetentionPolicy.RUNTIME)
:表示该注解只被保留在 class 文件中,并且可以被反射机制读取到。
注解中定义属性
public @interface MyAnnotation{
/*MyAnnotation的name属性*/
String name();
String since();
int age() default 5; //属性指定默认值,使用注解时有默认值的可以不写
String value();
}
使用:
1、如果一个注解当中有属性,则必须给属性赋值,除非该属性使用 default 指定了默认值。
@MyAnnotation(name="gao",since="9")
2、如果属性名为value
并且只有这一个属性,则使用注解时对应的属性值可以不写。
3、注解当中的属性可以是哪种类型?
答:可以是:byte\short\int\long\float\double\boolean\char\String\Class\枚举类型
及以上类型的数组形式。
反射注解
如果获取类上注解的属性值,必须先获取类,然后通过类获取类上的注解,最后获取注解属性值。
如果获取在方法上的注解属性值,必须先获取类,然后获取类的方法,通过方法获取方法上的注解,最后获取注解的属性值。
//只允许该注解标注类、方法
@Target({ElementType.TYPE,ElementType.METHOD})
//希望这个注解可以被反射
@Retention(RetentionPolicy.RNUTIME)
public @interface MyAnnotation{
String value() default "zhang";
}
//注解测试类
@MyAnnotation("gao")
public class MyAnnotationTest{
int i;
public MyAnnotationTest(){
}
@MyAnnotation
public void doSome(){
int i ;
}
}
//反射注解测试类
public class Reflect AnnotationTest{
public static void main(String[] args) throws Exception{
//获取这个类
Class c = Class.forName("com.reflect.www.MyAnnotationTest");
//判断是否有@MyAnnotation这个注解,并获取注解对象和属性值
if(c.isAnnotationPresent(MyAnnotation.class)){//如果有该注解对象则返回true
//获取注解对象
MyAnnotation myAnnotation = (MyAnnotation)c.getAnnotation(MyAnnotation.class); //@com.reflect.www.MyAnnotationTest
//获取注解对象的属性
String value = myAnnotation.value();
System.out.println(value);//返回最后一次修改的value值
}
}
}
注解在开发中的作用
需求:假设有一个注解@Id
,这个注解只能出现在类上面,当类上有这个注解时,要求这个类中必须有一个 int 类型的 id 属性,如果没有则报异常,有则正常执行。
//该注解只能出现在类上
@Target(ElementType.TYPE)
//该注解可以被反射机制读取
@Retention(RetentionPolicy.RUNTIME)
public @interface Id{
}
//带有注解的类
@Id
public class Test{
int id;
String name;
}
//测试类
public class AnnotationTest{
public static void main(String[] args){
//获取类
Class c = Class.forName("com.reflect.www.Test");
//判断类上是否有注解@Id
if(c.isAnnotationPresent(Id.class)){
//获取类的属性
Field[] fields = c.getDeclaredFields();
boolean ok = false; //默认标记是否合法
for(Field[] field : fields){
if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){ //当有id属性且识int类型时,表示合法
ok = true;
break;
}
}
//当不合法时报错
if(!ok){
throw new HasNotIdPropertyException("被@Id注解标注的类中没有int类型的id属性,不合法!");
}
}
}
}
//自定义异常
public class HasNotIdPropertyException extends RuntimeException{
public HasNotIdPropertyException(){}
public HasNotIdPropertyException(String s){
super(s);
}
}