Annotation-注解

Annotation-注解:(注释类型)

  • 1、注解Annotation是一种引用数据类型。编译之后也是生成xxx.class文件。
  • 2、自定义注解: public @interface 注解类型名{ }

Annotation-JDK内置注解:元注解:用来标注“注解类型”的“注解”,称为元注解。

常见的元注解: @ Retention

  • @Target注解:是元注解,Target注解用来标注“被标注的注解”可以出现在哪些位置上。
  • 出现在"方法":       @Target(ElementType.METHOD)
  • 出现在"属性":       @Target(ElementType.FIELD)
  • 出现在"局部变量": @Target(ElementType.LOCAL_VARIABLE)
  • 出现在"包":           @Target(ElementType.PACKAGE)
  • 出现在"类":           @Target(ElementType.TYPE
  • 允许该注解可以标注类、方法  :@Target( {ElementType.TYPE, ElementType.METHOD} )

常见的元注解:

@ Retention :source源文件;class文件;  runtime保存class文件,可被反射机制读取

  • Retention注解:是元注解,Retention注解用来标注“被标注的注解”最终保存在哪里。
  • 保留在java源文件中:  @Retention(RetentionPolicy.SOURCE)
  • 保存在class文件中:   @Retention(RetentionPolicy.CLASS)
  • 保存在class文件中,可被反射机制读取@Retention(RetentionPolicy.RUNTIME)

Annotation-JDK内置注解:java.lang包下的注释类型:

  • @Deprecated 用 @Deprecated 注释的程序元素,过时的方法;不鼓励使用这样的元素,因为它很危险或存在更好的选择。
  • @Override 表示一个方法声明打算重写超类中的另一个方法声明。
  • @SuppressWarnings-忽略注解中声明的警告
//JDK中源代码
public @interface Override {
}
public class AnnotationTest02 {
    //@Override  报错
    private int no; //属性
    @Override   // @Override这个注解只能注解方法。
    public String toString() {   //方法
        return "toString";
    }
}

当注解中有属性时:

public @interface MyAnnotation {

    /**
     * 通常在注解当中可以定义属性,以下这个是MyAnnotation的name属性。
     * 看着像1个方法,但实际上我们称之为属性name。
     * @return
     */
    String name();  
    //颜色属性
    String color();
    //年龄属性
    int age() default 25; //属性指定默认值
}


public class MyAnnotationTest {

    // 报错的原因:如果一个注解当中有属性,那么必须给属性赋值。(除非该属性使用default指定了默认值。)
    /*@MyAnnotation
    public void doSome(){ }*/

     //指定name属性的值就好了。
    //@MyAnnotation(属性名=属性值,属性名=属性值,属性名=属性值)
    @MyAnnotation(name = "zhangsan", color = "红色")
    public void doSome(){

    }
}

注解中的属性类型:

public @interface MyAnnotation {
    /*
    注解当中的属性可以是哪一种类型?
        属性的类型可以是:
            byte short int long float double boolean char String Class 枚举类型
            以及以上每一种的数组形式。
     */
    int value1();

    String value2();

    int[] value3();

    String[] value4();

    Season value5();

    Season[] value6();  //枚举:一年四季

    Class parameterType();

    Class[] parameterTypes();
}

 @Targe 联合 @Retention

允许反射机制获取类中属性信息

//只允许该注解可以标注类、方法
@Target({ElementType.TYPE, ElementType.METHOD})
// 希望这个注解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    /*
    value属性。
     */
    String value() default "北京大兴区";
}


@MyAnnotation("上海浦东区")
public class MyAnnotationTest {
    //@MyAnnotation
    int i;
    //@MyAnnotation
    public MyAnnotationTest(){ }
    @MyAnnotation
    public void doSome(){
        //@MyAnnotation
        int i;
    }

}

public class ReflectAnnotationTest {
    public static void main(String[] args) throws Exception{
        // 获取这个类
        Class c = Class.forName("com.bjpowernode.java.annotation5.MyAnnotationTest");
        // 判断类上面是否有@MyAnnotation
        //System.out.println(c.isAnnotationPresent(MyAnnotation.class)); // true
        if(c.isAnnotationPresent(MyAnnotation.class)){
            // 获取该注解对象
            MyAnnotation myAnnotation = (MyAnnotation)c.getAnnotation(MyAnnotation.class);
            //System.out.println("类上面的注解对象" + myAnnotation); // @com.bjpowernode.java.annotation5.MyAnnotation()
            // 获取注解对象的属性怎么办?和调接口没区别。
            String value = myAnnotation.value();
            System.out.println(value);
        }

        // 判断String类上面是否存在这个注解
        Class stringClass = Class.forName("java.lang.String");
        System.out.println(stringClass.isAnnotationPresent(MyAnnotation.class)); // false
    }
}

反射机制获取注解属性信息

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    //username属性
    String username();
    //password属性
    String password();
}

public class MyAnnotationTest {

    @MyAnnotation(username = "admin", password = "456456")
    public void doSome(){

    }

    public static void main(String[] args) throws Exception{
        // 获取MyAnnotationTest的doSome()方法上面的注解信息。
        Class c = Class.forName("com.bjpowernode.java.annotation6.MyAnnotationTest");
        // 获取doSome()方法
        Method doSomeMethod = c.getDeclaredMethod("doSome");
        // 判断该方法上是否存在这个注解
        if(doSomeMethod.isAnnotationPresent(MyAnnotation.class)) {
            MyAnnotation myAnnotation = doSomeMethod.getAnnotation(MyAnnotation.class);
            System.out.println(myAnnotation.username());
            System.out.println(myAnnotation.password());
        }
    }

}

注解在开发中有 需求:

  • 假设有这样一个注解,叫做:@Id   这个注解只能出现在类上面,当这个类上有这个注解的时候,
  •  要求这个类中必须有一个int类型的id属性。如果没有这个属性
  •  就报异常。如果有这个属性则正常执行!
//这个注解@Id用来标注类,被标注的类中必须有一个int类型的id属性,没有就报异常。
// 表示这个注解只能出现在类上面
@Target(ElementType.TYPE)
// 该注解可以被反射机制读取到
@Retention(RetentionPolicy.RUNTIME)
public @interface MustHasIdPropertyAnnotation {   }


@MustHasIdPropertyAnnotation
public class User {
    int id;
    String name;
    String password;
}

 

/*
自定义异常  继承:RuntimeException 提供无参构造,和有参构造
 */
public class HasNotIdPropertyException extends RuntimeException {
    public HasNotIdPropertyException(){

    }
    public HasNotIdPropertyException(String s){
        super(s);
    }
}

 

public class Test {
    public static void main(String[] args) throws Exception{
        // 获取类
        Class userClass = Class.forName("com.bjpowernode.java.annotation7.User");
        // 判断类上是否存在Id注解
        if(userClass.isAnnotationPresent(MustHasIdPropertyAnnotation.class)){
            // 当一个类上面有@MustHasIdPropertyAnnotation注解的时候,要求类中必须存在int类型的id属性
            // 如果没有int类型的id属性则报异常。
            // 获取类的属性
            Field[] fields = userClass.getDeclaredFields();
            boolean isOk = false; // 给一个默认的标记
            for(Field field : fields){
                if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){
                    // 表示这个类是合法的类。有@Id注解,则这个类中必须有int类型的id
                    isOk = true; // 表示合法
                    break;
                }
            }

            // 判断是否合法
            if(!isOk){
                throw new HasNotIdPropertyException("被@MustHasIdPropertyAnnotation注解标注的类中必须要有一个int类型的id属性!");
            }

        }
    }
}

 

posted @ 2022-04-27 23:52  280887072  阅读(40)  评论(0编辑  收藏  举报