注解

注解(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);
    }
}
posted @ 2020-08-09 20:25  莫哈德  阅读(104)  评论(0编辑  收藏  举报
/*地址栏logo*/