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){}
}

 

posted on 2021-11-04 09:33  homle  阅读(68)  评论(0编辑  收藏  举报