zoukankan      html  css  js  c++  java
  • java中的注解

    1、概述
    2、内置注解
    ---2.1Override注解
    ---2.2Deprecated注解
    3、元注解
    ---3.1关于Target注解
    ---3.2关于Retention注解
    4、注解中定义属性
    5、反射注解
    6、通过反射获取注解对象属性的值
    7、注解在开发中的作用
    更多关于注解见:
    链接一
    链接二

    概述

    1、注解:Annotation是一种引用数据类型。编译之后也是生成xx.class文件。
    2、语法格式为:
    [修饰符列表] @interface 注解类型名{}
    3、注解怎么使用?
    注解使用时的语法格式是:@注解类型名
    Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。(默认情况下,注解可以出现在任意位置。)
    4、例:

    @DemoAnno
    public class Demo {
        @DemoAnno
        private int no;
        @DemoAnno
        public Demo() {
        }
        @DemoAnno
        private void m(){
            @DemoAnno
            int a = 1;
        }
    }
    
    @DemoAnno
    interface MyInterface{
    }
    
    @DemoAnno
    enum S {
        ANN
    }
    
    @DemoA
    public @interface DemoAnno {
    }
    

    5、一些内置注解
    Deprecated
    注释@Deprecated的程序元素是程序员不鼓励使用的程序元素,通常是因为它是危险的,或者因为存在更好的替代方法。
    FunctionalInterface
    使用的信息注释类型,以指示在接口类型声明旨在是一个 功能接口由Java语言规范所定义的。
    Override
    表示方法声明旨在覆盖超类型中的方法声明。
    SafeVarargs
    程序员断言注释方法或构造函数的正文不会对其varargs参数执行潜在的不安全操作。
    SuppressWarnings
    表示在注释元素(以及注释元素中包含的所有程序元素)中应该抑制命名的编译器警告。

    内置注解

    Override注解

    1、源代码:
    public @interface Override {}
    2、是一个标识性注解,给编译器做参考。
    方法上有这个注解的时候,编译器会自动检查该方法是否重写了父类的方法。如果没有重写会报错。这个注解只是在编译阶段起作用,和运行期无关。
    3、只能注解方法,因为被Target限制了:
    @Target(ElementType.METHOD)

    Deprecated注解

    1、被其标识后,表示被标识的元素已过时,告知程序员已过时,有更好的方案存在。
    2、图例(其中过时的方法会加横杠):
    在这里插入图片描述
    运行后:
    在这里插入图片描述
    但是会有警告:
    在这里插入图片描述

    元注解

    • 概述
      1、用来标注“注解类型”的“注解”,称为元注解。
      2、常见元注解:
      @Retention
      @Target
    关于Target注解

    1、Target注解用来标注“被标注的注解”可以出现在哪些位置上。
    2、@Target(ElementType.METHOD)
    表示“被标注的注解“只能出现在方法上。

    关于Retention注解

    1、Retention注解用来标注“被标注的注解”最终保存在哪里。
    2、@Retention(RetentionPolicy.SOURCE)
    表示该注解只被保留在java源文件中。
    @Retention(RetentionPolicy.CLASS)
    表示该注解被保存在class文件中
    @Retention(RetentionPolicy.RUNTIME)
    表示该注解被保存在class文件中,并且可以被反射机制所读取。

    注解中定义属性

    • 属性类型
      属性的类型可以是:byte、short、int、long、float、double、boolean、char、string、class、枚举类型,以及它们的每一种的数组形式。
    • 代码示例
    public @interface DemoAnno {
        //定义name属性
        String name();
        //定义age属性
        int age();
        //定义性别(指定属性的默认值)
        String sex() default "男";
    }
    
    public class Demo {
        /*报错的原因:注解中有属性,没有给属性赋值。
        * (除非该属性使用default指定了默认值)*/
        /*@DemoAnno()
        public void doSome(){ }*/
    
        //@DemoAnno(属性名=属性值,属性名=属性值...)
        @DemoAnno(name = "zhangsan",age = 1)
        public void doSome(){
            
        }
    }
    
    • 属性是value时可以省略
      1、限制条件:有且只有一个属性名叫value。
      2、代码示例:
    public @interface DemoAnno {
        //定义value属性
        String value();
    }
    
    public class Demo {
    
        @DemoAnno(value = "v")
        public void doSome(){
        }
    
        //省略了“value = ”
        @DemoAnno("vv")
        public void doOther(){
        }
    }
    

    3、不止有value一个属性时:

    public @interface DemoAnno {
        //定义value属性
        String value();
        //再加一个属性
        String name();
    }
    
    public class Demo {
    
        //此时就不能省略value
        @DemoAnno(value = "v", name = "zhangsan")
        public void doSome(){
        }
    }
    
    • 属性是数组时
    public enum Season {
        SPRING, SUMMER, AUTUMN, WINTER
    }
    
    public @interface DemoAnno {
        String name();
        String[] hobby();
        //枚举数组
        Season[] seasonArr();
    }
    
    public class Demo {
    
        //数组中只有一个元素时,大括号可以省略
        @DemoAnno(name = "v",
                hobby = "zhangsan",
                seasonArr = Season.SUMMER)
        public void doSome(){
        }
    
        @DemoAnno(name = "v",
                hobby = {"111@qq.com","222@qq.com"},
                seasonArr = {Season.SPRING, Season.AUTUMN})
        public void doOther(){
        }
    }
    

    反射注解

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    //该注解只能标注类、方法
    @Target({ElementType.TYPE, ElementType.METHOD})
    //该注解可以被反射
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DemoAnno {
        String value() default "zhangsan";
    }
    
    @DemoAnno("lisi")
    public class Demo {
        @DemoAnno
        public void doSome(){
            int i;
        }
    }
    
    public class DemoTest {
        public static void main(String[] args) throws Exception{
            Class c = Class.forName("Demo");
            /*判断类上面是否有@DemoAnno
            * 输出:true*/
            //System.out.println(c.isAnnotationPresent(DemoAnno.class));
            if (c.isAnnotationPresent(DemoAnno.class)){
                //获取该注解对象
                DemoAnno demoAnno = (DemoAnno)c.getAnnotation(DemoAnno.class);
                System.out.println("类上的注解对象是:"+ demoAnno);
                //获取注解对象的属性
                String s = demoAnno.value();
                System.out.println(s);
            }
        }
    }
    

    输出:
    在这里插入图片描述

    通过反射获取注解对象属性的值

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DemoAnno {
        String username();
        String password();
    }
    
    import java.lang.reflect.Method;
    
    public class Demo {
        @DemoAnno(username = "admin", password = "123")
        public void doSome(){
        }
    
        public static void main(String[] args) throws Exception{
            //获取Demo的doSome()方法上面的注解信息
            Class c = Class.forName("Demo");
            //获取doSome()方法
            Method doSomeMethod = c.getDeclaredMethod("doSome");
            //判断该方法上是否存在这个注解
            if (doSomeMethod.isAnnotationPresent(DemoAnno.class)){
                DemoAnno demoAnno = doSomeMethod.getAnnotation(DemoAnno.class);
                System.out.println(demoAnno.username());
                System.out.println(demoAnno.password());
            }
        }
    }
    

    输出:
    在这里插入图片描述

    注解在开发中的作用

    1、假如以这样一个需求:
    有一个注解叫:@DemoAnno。这个注解只能出现在类上面,当这个类上有这个注解的时候,要求这个类中必须有一个int类型的id属性。如果没有这个属性就报异常,如果有这个属性则正常执行。
    2、代码示例:

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DemoAnno {
    }
    
    @DemoAnno()
    public class Demo {
        //int id;
        String name;
        String psw;
    }
    
    /*自定义异常*/
    public class No_Id_Exception extends RuntimeException{
        public No_Id_Exception() {
        }
    
        public No_Id_Exception(String message) {
            super(message);
        }
    }
    
    import java.lang.reflect.Field;
    
    public class DemoTest {
        public static void main(String[] args) throws Exception{
            Class demoClass = Class.forName("Demo");
            //布尔标记
            boolean isOk = false;
            if (demoClass.isAnnotationPresent(DemoAnno.class)){
                /*有注解的话,要求必须存在int类型的id属性*/
                //获取类的属性
                Field[] fields = demoClass.getDeclaredFields();
                for (Field field:fields) {
                    if ("id".equals(field.getName())
                            && "int".equals(
                                    field.getType().getSimpleName())){
                        //合法
                        isOk = true;
                        break;
                    }
                }
                if (!isOk) {
                    throw new No_Id_Exception(
                            "没有int类型的id属性");
                }
            }
        }
    }
    

    有int id时(无异常):
    在这里插入图片描述
    没有int id时:
    在这里插入图片描述

  • 相关阅读:
    捕获Java线程池执行任务抛出的异常
    Java Singleton 单例模式
    深度解析Java内存的原型及工作原理
    使用Spring管理数据源连接池
    Java中用内存映射处理大文件
    基于Java阻塞队列的搜索实例
    Java学习之将图片文件保存到数据库
    Java使用反射调用方法
    Java程序员易犯的10个SQL错误
    Hibernate中的数据库增改删查操作
  • 原文地址:https://www.cnblogs.com/yu011/p/13198833.html
Copyright © 2011-2022 走看看