zoukankan      html  css  js  c++  java
  • Java 注解认知

    1. 注解定义

      注解是一种特殊的注释,是一种引用数据类型,可以注解Java中所有数据类型,可以出现在任何位置。

    2. 注解的语法格式

    public @interface OtherAnnotation{    
    }

      使用@interface定义注解,名字是OtherAnnotation,意味着它实现了java.lang.annotaion.Annotaion接口。Annotation接口的实现细节都是由编译器完成的,通过@interface定义注解后,该注解不能继承其他的注解或接口。

    @OtherAnnotation
    public @interface MyAnnotation{    
    }

      定义注解后,可以使用@OtherAnnotation来使用这个注解,注解也可以“注解”注解。

    package com.lewang.annotaion;
    
    @MyAnnotaion
    public class AnnotaionTest01{
        @Deprecated
        public String name;
        @MyAnnotaion
        private int no;
        @MyAnnotaion
        public AnnotationTest01{
            
        }
        @MyAnnotaion
        public static void m1(){
            
        }
        @MyAnnotaion
        public void m2(){
            
        }
    }
    @MyAnnotaion
    interface MyInterface{
        
    }
    @MyAnnotaion
    enum Season{
        SPRING,SUMMER,WINTER
    }

      注解是一种引用数据类型,几乎可以注解java中所有数据类型。

    3. 自定义注解

      自定义注解如果由属性,那么注解需要赋值,默认类型可以不用赋值

    public @interface MyAnnotation01{
        //name属性
        String name();
        //email属性
        String email();
        //age属性
        int age() default 23;
    }
    public class Annotation02{
        @MyAnnotation(name="james",email="james23@google.com")
        public void m1(){
            
        }
    }

      自定义注解属性值是value时,value可以省略

    public @interface MyAnnotation02{
        //属性是value
        String value();
    }
    public class AnnotationTest02{
        
        @MyAnnotation02(value = "a")
        public void m1(){}
        
        @MyAnnotation02("b")
        public void m2(){}
    }

      注解属性可以是枚举类型;当属性是字符串时,只有一个字符串时可以不用带大括号

    public enum Season{
        SRPING,WINTER,SUMMER
    }
    public @interface MyAnnotation03{
        int age();
        String[] name();
        Season[] value(); //属性可以时枚举类型
    }
    public class AnnotationTest03{
        
        @MyAnnotation03(age=37,name={"james","kobe"},value=Season.WINTER)
        public void m1(){}
        
        @MyAnnotation03(age=37,name="kobe",value=Season.SPRING)  //当字符串属性时只有一个字符串,可以不用带大括号
        public void m2(){}
    }

    4. 元注解

      用来标注“注解类型”的注解,通常用在注解的定义上。

    @Target({ElementType.METHOD,ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation{
        String value();
    }

      Java中常见的元注解

      @Target:用来标注“被标注的注解 ”可以出现在哪些位置上

        @Target(ElementType.METHOD,ElementType.TYPE):表示“被标注的注解”可以出现在方法上,可以出现在类上,不能出现其他类型上;

      @Retention:用来标注“被标注的注解”最终保存在哪里

        @Retention(RetentionPolicy.SOURCE):表示该注解只被保存在java源文件中;

        @Retention(RetentionPolicy.CLASS):表示该注解被保存在class文件中;

        @Retention(RetentionPolicy.RUNTIEM):表示该注解被保存在class文件中,并且该注解可以被反射机制读取;

      @Documented:表示该注解可以出现在javadoc中

      @Deprecated:该注解标注的内容过时,不再推荐使用

      @Override:只能标注方法,表示该方法覆盖父类中的方法

      示例1:元注解和反射(@Target,@Retention)

    /*
        元注解只能注解类和方法,不能注解其他类型,可以保存在class文件中,可以被反射
    */
    
    @Target({ElementType.METHOD,ElementType.TYPE})  
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation04{
        String value();
    }
    @MyAnnotation04("aa")
    public class AnnotationTest04{
        
        @MyAnnotation04("bb")
        public void m1(){}
        
        //@MyAnnotation04("dd")  //错误: 注释类型不适用于该类型的声明
        private int i;
    }
    public class AnnotationTest05{
        public static void main(String[] args) throws Exception{
            
            Class annotaionClass = Class.forName("com.lewang.annotation04.AnnotationTest04");
            
            //类AnnotationTest04是否有MyAnnotation04注解
            System.out.println(annotaionClass.isAnnotationPresent(MyAnnotation04.class));  //true
            
            if(annotaionClass.isAnnotationPresent(MyAnnotation04.class)){
                //获取注解对象
                MyAnnotation04 myAnnotation = (MyAnnotation04)annotaionClass.getAnnotation(MyAnnotation04.class); 
                System.out.println("类上的注解:" + myAnnotation);
                String annotationvalue = myAnnotation.value();  //获取注解属性
                System.out.println(annotationvalue);
            }
            
            Class stringclass = Class.forName("java.lang.String");
            System.out.println(stringclass.isAnnotationPresent(MyAnnotation04.class));  //false
        }
    }

      示例2:反射获取注解属性值

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation05{
        String username();
        String password();
    }
    public class AnnotationTest06{
        
        @MyAnnotation05(username="adm",password="123")
        public void m1(){}
        
        public static void main(String[] args) throws Exception{
            Class annotationclass = Class.forName("com.lewang.annotation05.AnnotationTest06");
            Method method = annotationclass.getDeclaredMethod("m1");
            if(method.isAnnotationPresent(MyAnnotation05.class)){
                MyAnnotation05 myannotation = method.getAnnotation(MyAnnotation05.class);
                System.out.println(myannotation.username());
                System.out.println(myannotation.password());
            }
        }
    }

     示例3:注解的应用,创建一个注解,用这个注解注解一个类,在另一个类中反射类,判断类中是否有需要的属性

    public class MyException extends Exception{
        public MyException(){}
        public MyException(String s){super(s);}
    }
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation06{
        
    }
    @MyAnnotation06
    public class User{
        //int id;
        String name;
    }
    public class AnnotationTest07{
        public static void main(String[] args) throws Exception{
            Class userclass = Class.forName("com.lewang.annotaion07.User");
            if(userclass.isAnnotationPresent(MyAnnotation06.class)){
                Field[] fields = userclass.getDeclaredFields();
                boolean flag = false;
                for(Field field : fields){
                    if("id".equals(field.getName()) && "int".equals(field.getType().getName())){
                        flag = true;
                        break;
                    }
                }
                if(!flag){
                    throw new MyException("被MyAnnotation06注解的类必须要有id属性");
                }
            }
        }
    }

      @Deprecated :标注表示过时的,不推荐使用的,在IDEA中调用会加一横线

      @Override : 标注表示会覆盖父类中同名的方法,如果父类中没有同名的方法,则会产生编译告警

    public class OverrideTest{
        
        @Override
        public String toString(){
            return "Override toString";
        }
        
        @Override
        public String getString(){    // 错误: 方法不会覆盖或实现超类型的方法
            return "getString";
        }
        
        public static void main(String[] args){}
    }
  • 相关阅读:
    一道leetcode题的收获如何比较字符串的大小重写sort中的compare[](string &s,string &t){return s+t>t+s};
    unsigned int表示负数问题
    fork()和printf()几点注意细节
    32位机中数据问题
    C++隐藏机制
    ||,&&,++i解答
    enum忽略知识点
    硬链接与软链接
    20145215实验五 Java网络编程及安全
    证书与keytool
  • 原文地址:https://www.cnblogs.com/homle/p/15502853.html
Copyright © 2011-2022 走看看