注解:Annotation

一、注解

  1. 注解(Annotation)是一种引用数据类型,编译之后也是生成xxx.class文件。
  2. 自定义注解的语法格式:
    [修饰符列表] @interface 注解类型名{
    }
    
  3. 注解的使用:
    • 注解使用时的语法格式:@注解类型名
    • 注解可以出现在类上、属性上、方法上、变量上等…注解还可以出现在注解类型上。
  4. JDK内置的注解:
    • java.lang包下的注解类型:
      • Deprecated:用@Deprecated 注释的程序元素表示该元素已过时,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。
      • Override:表示一个方法声明打算重写超类中的另一个方法声明。
      • SuppressWarnings:指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。
  5. 元注解:用来标注"注解类型"的"注解",称为"元注解"。
    • 常见的元注解:
      • Target:用来标注"被标注的注解"可以出现在哪些位置上。
        • @Target(ElementType.METHOD): 表示"被标注的注解"只能出现在方法上
        • @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE}): 表示"被标注的注解"可以出现在构造方法上,字段上,局部变量上,方法上,包上,模块上,参数上,类上。
      • Retention:用来标注"被标注的注解"最终保存在哪里。
        • @Retention(RetentionPolicy.SOURCE): 表示"被标注的注解"只被保留在java源文件中。
        • @Retention(RetentionPolicy.CLASS): 表示"被标注的注解"被保存在class文件中。
        • @Retention(RetentionPolicy.RUNTIME): 表示"被标注的注解"被保存在class文件中,并且可以被反射机制所读取。
  6. 注解当中可以定义属性
    • 如果一个注解当中有属性,那么注解在标注时必须给属性赋值。(除非该属性使用default指定了默认值)

    • 如果一个注解的属性的名字是value,并且只有一个属性的话,在使用注解的时候,该属性名可以省略。

    • 注解当中属性的类型可以是:
      byte、short、int、long、float、double、boolean、char、String、Class、枚举类型
      以及以上每一种的数组形式。

    • 如果注解当中属性为数组,在使用注解时如若数组有多个元素,用大括号表示数组;如果数组中只有一个元素,大括号可以省略。

    public @interface MyAnnotation {
       /**
        * 我们通常在注解当中可以定义属性,以下这个是MyAnnotation的name属性。
        * 看着像1个方法,但实际上我们称之为属性name。
        */
       String name();
       //颜色属性
       String color();
       //年龄属性
       int age() default 25; //属性指定默认值
    }
    
    public class MyAnnotationTest {
       //@MyAnnotation(属性名=属性值,属性名=属性值,属性名=属性值)
       //年龄属性有默认值可以不赋值,也可以赋指定的值
       @MyAnnotation(name = "zhangsan", color = "红色")
       public void doSome(){
       }
    }
    
  7. 通过反射机制获取Java对象中的注解(注解属性)
    @Target({ElementType.METHOD,ElementType.TYPE})//该注解只能出现在类和方法上
    @Retention(RetentionPolicy.RUNTIME)//该注解的保存策略为可以保存到class文件并可以被反射
    public @interface MyAnnotation {
        //username属性
        String username();
        //password属性
        String password();
    }
    ---------------------------------------------------------------------------------------------------
    @MyAnnotation(username = "zhangsan",password = "123")
    public class MyAnnotationTest {
        @MyAnnotation(username = "lisi", password = "1234")
        public void doSome() {
        }
    }
    ---------------------------------------------------------------------------------------------------
    public class ReflectAnnotationTest {
        public static void main(String[] args) {
            // 1.反射MyAnnotationTest类上面的@MyAnnotation注解
            try {
                //通过反射机制获取类class文件
                Class cc = Class.forName("com.javaSE.annotation.annotation02.MyAnnotationTest");
                //判断类上面是否存在@MyAnnotation注解
                if (cc.isAnnotationPresent(MyAnnotation.class)) {
                    //存在则获得注解对象
                    Annotation ccAnnotation = cc.getAnnotation(MyAnnotation.class);
                    System.out.println(ccAnnotation);//@com.javaSE.annotation.annotation02.MyAnnotation(username="zhangsan", password="123")
                    //获得注解对象中的属性
                    String username = ((MyAnnotation) ccAnnotation).username();
                    String password = ((MyAnnotation) ccAnnotation).password();
                    System.out.println(username);//zhangsan
                    System.out.println(password);//123
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            // 2.反射MyAnnotationTest类中方法上面的@MyAnnotation注解
            try {
                //通过反射机制获取class文件
                Class cm = Class.forName("com.javaSE.annotation.annotation02.MyAnnotationTest");
                //通过反射机制获取类中的方法
                Method[] declaredMethods = cm.getDeclaredMethods();
                for (Method method : declaredMethods) {
                    //判断方法上是否有@MyAnnotation注解
                    if (method.isAnnotationPresent(MyAnnotation.class)) {
                        //存在则获取注解对象
                        MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
                        System.out.println(annotation);//@com.javaSE.annotation.annotation02.MyAnnotation(username="lisi", password="1234")
                        //获得该注解对象的属性
                        System.out.println(annotation.username());//lisi
                        System.out.println(annotation.password());//1234
                    }
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    

二、注解在开发中的应用

  1. 简单案例

    假设有这样一个注解,叫做:@Id
    这个注解只能出现在类上面,当这个类上有这个注解的时候,要求这个类中必须有一个int类型的id属性。如果没有这个属性就报异常。如果有这个属性则正常执行!

    //自定义异常:没有id属性异常
    public class NoIdPropertyException extends RuntimeException {
        public NoIdPropertyException() {
        }
    
        public NoIdPropertyException(String message) {
            super(message);
        }
    }
    -----------------------------------------------------------------------------------------------------
    // 这个注解用来标注类,被标注的类中必须有一个int类型的id属性,没有就报异常。
    @Target(ElementType.TYPE)//该注解只能出现在类上面
    @Retention(RetentionPolicy.RUNTIME)//该注解能保存在class文件中并且能被反射机制读取
    public @interface IDAttributeMustBePresentAnnotation {
    }
    -----------------------------------------------------------------------------------------------------
    //被该注解标注的类必须有int类型的id属性,没有则抛出异常
    @IDAttributeMustBePresentAnnotation
    public class User {
    //    int id;
        String name;
        boolean sex;
        String password;
    }
    -----------------------------------------------------------------------------------------------------
    public class Test {
        public static void main(String[] args) {
            try {
                //通过反射机制获取类
                Class c = Class.forName("com.javaSE.annotation.annotation03.User");
                //判断该类上是否存在@IDAttributeMustBePresentAnnotation注解
                if (c.isAnnotationPresent(IDAttributeMustBePresentAnnotation.class)) {
                    //存在则判断该类中是否存在int类型的id属性
                    boolean isExists = false;//定义一个默认为不存在的判断
                    //获取类中的所有字段/属性
                    Field[] fields = c.getDeclaredFields();
                    for (Field field : fields) {
                        //判断字段/属性是否存在int类型的id属性
                        if ("int".equals(field.getType().getSimpleName()) && "id".equals(field.getName())) {
                            //存在则为true
                            isExists = true;
                            break;
                        }
                    }
                    //不存在则抛出异常
                    if (!isExists) {
                        throw new NoIdPropertyException("被@IDAttributeMustBePresentAnnotation标注的类必须有一个int类型的id属性");
                    }
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值