第十九天 注释

定义
  • 注解,亦叫做注释,英文单词:Annotation
  • 注解Annotation是一种引用数据类型,编译之后也是生成xxx.class文件
  • 怎么样自定义注解?语法格式是啥?
[ 修饰符列表 ] @interface 注解类型名{ }
  • 使用注解的语法格式:
@注解类型名
  • 注解用在什么地方法
    • 注解可以用在类上、属性上、方法上、变量上…
    • 注解甚至能出现在注解类型上

注解类

public @interface MyAnnotation {
}

注解使用的位置

package Day19注解;

public class Test01 {
    @MyAnnotation       //属性
    private int no;

    @MyAnnotation       //构造方法
    public Test01() {}

    @MyAnnotation       //静态方法
    public static void doSome(){}

    @MyAnnotation       //实例方法
    public void doOther(){
        @MyAnnotation   //局部变量
        int i = 1;
    }

    public void m1(@MyAnnotation String name){}     //形参
}

@MyAnnotation       //接口
interface MyInterface{}

@MyAnnotation       //枚举
enum Season{
    SPRING,SUNMER,AUTUMN,WINTER
}

package Day19注解;

@MyAnnotation       //其他注释
public @interface OtherAnnotation {
}

综上所述:注释能出现在:属性、构造方法、静态方法、实例方法、局部变量、接口、枚举类型、其他注释上

Override注解
注解类型描述
Deprecated一个程序单元注释”不是一个程序员应该使用,通常是因为它是危险的,因为一个更好的选择的存在。
Override表示一个方法声明的目的是覆盖父类方法声明。
SuppressWarnings指示在注释元素(和包含在注释元素中的所有程序元素中)应被抑制命名的编译器警告。

Override注解

package Day19注解;

public class Test02 {
    /*
    Override的源码:
        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.SOURCE)
        public @interface Override {}
    * */

    @Override
    public String toString() {
        return "toString";
    }
}

解释:
@Override这个注解只能注解方法
该注解是给编译器参考的,和运行阶段没有关系,如果java中的方法带有这个注解,编译器就会进行编译检查,如果该方法没有重写父类的方法,则报错

元注解
  • 定义:标注“注解类型”的注解
  • 常见的元注解
    • Target
    • Retention
  • Target
    • 这是一个元注解,用来标注“注解类型”的注解
    • 作用:限制被标注的注解出现的位置
    • 实例
@Target(ElementType.METHOD)
//表示被该注解标注的注解只能出现在方法上
  • Retention
    • 标注“被标注的注解”最终保存在哪里
    • 实例
@Retention(RetentionPolicy.SOURCE)
//表示该注解只是被保留在Java源文件中

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

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

作用:告诉其他人这个东西已经过时了,目前已经有了更好的解决方案

package Day19注解;

@Deprecated
public class Test03 {
    public static void main(String[] args) {
        Test03 test03 = new Test03();
        test03.doSome();
    }

    @Deprecated
    public static void doSome(){
        System.out.println("do Something...");
    }

    public static void doOther(){
        System.out.println("do Other thing...");
    }
}

class Test04{
    public static void main(String[] args) {
        Test03 test03 = new Test03();
        test03.doOther();

        try {
            Class<?> aClass = Class.forName("Day19注解.Test03");
            Object object = aClass.newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wC73NyzH-1612032291499)(en-resource://database/708:1)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s2ZWQoiH-1612032291501)(en-resource://database/710:1)]

表示该方法和该类均被淘汰了

注解定义属性

自定义属性

package Day19注解;

public @interface MyAnnotation {
    String name();

    String color();

    int age = 21;   //属性指定默认值
}

测试

package Day19注解;

public class Test05 {
//    @YourAnnotation()
//    public void doSome(){}
//    对于元素name,color, 注释 @Day19注解.YourAnnotation 缺少默认值

    @YourAnnotation(name = "张三", color = "black")
    public void doSome(){}

    public static void main(String[] args) {}


}

注意事项:

  1. 在注解中也是可以定义属性的
  2. 虽然属性后面有个小括号,看着很像是方法,但是这实际上就是注释的属性
  3. 如果注解中有属性,则必须给属性赋值,除非本身就使用default指定了默认值
属性是value的时候

当注解仅有一个value属性的时候:
注解类:

package Day19注解;

public @interface YourAnnotation2 {
    String value();
}

测试:

package Day19注解;

public class Test06 {

    @YourAnnotation2(value = "张三")
    public void doSome(){}

    @YourAnnotation2("李四")
    public void doOther(){}

    public static void main(String[] args) {}
}

注意事项:
当注释中仅有一个属性,且该属性的名字是value的时候,在调用该注释的时候,小括号中的“value = ”可以直接省略

当注释不仅仅有一个value属性的时候
注解类:

package Day19注解;

public @interface YourAnnotation3 {
    String value();

    String name();
}

测试:

package Day19注解;

public class Test07 {

    @YourAnnotation3(value = "李四", name = "张三")
    public void doSome(){}

    public static void main(String[] args) {}
}

注意事项:
当先将“value = ”省略的时候,去填name,IDEA会自动的将“value = ”加上,如果没有,则会报错

属性是一个数组
  • 注解的属性类型可以是:byte short int long float double boolean char String Class 枚举类型
package Day19注解;

public @interface MyAnnotation2 {
    int value1();

    String value2();

    int[] value3();

    String value4();

    Season value5();

    Season[] value6();

    Class parameterType();

    Class[] parameterTypes();
}

枚举:

package Day19注解;

public enum Season2 {
    SPRING,SUMMER,AUTUMN,WINTER
}

属性为枚举类型:

package Day19注解;

public @interface MyAnnotation3 {
    int age();
    
    String[] name();
    
    Season[] seasonArray();
}

测试:

package Day19注解;

public class Test08 {
    @MyAnnotation3(age = 21, name = {"张三", "李四"}, seasonArray = {Season.AUTUMN,Season.SPRING})
    public void doSome(){}


    @MyAnnotation3(age = 21, name = "张三", seasonArray = {Season.AUTUMN,Season.SPRING})
    public void doOther(){}
}

注意事项:

  1. 枚举类型的属性写入的时候,需要加枚举类型的名字
  2. 如果数组只有1个元素,大括号是可以省略的
反射注解

自定义注解:

package Day19注解;

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 MyAnnotation4 {
    String value() default "广东广州";
}

测试注解:

package Day19注解;

@MyAnnotation4("四川成都")
public class Test09 {
//    @MyAnnotation4("四川成都")    //因为Target标注限制,所以MA4注释不能注释属性
    int i;

//    @MyAnnotation4("四川成都")    //因为Target标注限制,所以MA4注释不能注释构造方法
    public Test09(){}

    @MyAnnotation4("四川成都")
    public void doSome(){
//        @MyAnnotation4("四川成都")    //因为Target标注限制,所以MA4注释不能注释局部变量
        int i;
        System.out.println("doSome...");
    }
}

通过反射获取类的注释

package Day19注解;

public class Test10 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取类
        Class<?> t9Class = Class.forName("Day19注解.Test09");

        //判断该类上是否存在MyAnnotation4注释
        if (t9Class.isAnnotationPresent(MyAnnotation4.class)){
            //获取该注释对象
            MyAnnotation4 t9ClassAnnotation = t9Class.getAnnotation(MyAnnotation4.class);
            //输出该注释对象
            System.out.println(t9ClassAnnotation);

            //获取注释对象的属性值
            String value = t9ClassAnnotation.value();
            //输出属性
            System.out.println(value);
        }

        //对比实验,判断String类上面有无@MyAnnotation4
        //获取类
        Class<?> aClass = Class.forName("java.lang.String");
        if (aClass.isAnnotationPresent(MyAnnotation4.class)){
            System.out.println(aClass.getAnnotation(MyAnnotation4.class));
        } else {
            System.out.println(aClass.getSimpleName() + "类型不存在MyAnnotation4注释");
        }
    }
}

注意事项:

  1. 是判断某个java文件是否存在某种类型的注释,所以获取的是该java文件的类,而不是该注释的类
  2. 获取到后就需要进行判断是否存在该注释,使用isAnnotationPresent()方法
通过反射获取注解对象的值

自定义注解:

package Day19注解;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation5 {
    String name();
    String id();
}

测试:

package Day19注解;

//获取本类doSome()方法上面的注释信息

import java.lang.reflect.Method;

public class Test11 {

    @MyAnnotation5(name = "张三", id = "001")
    public void doSome(){}

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        //获取本类
        Class<?> t11Class = Class.forName("Day19注解.Test11");

        //获取doSome()方法
        Method dsMethod = t11Class.getMethod("doSome");

        //判断doSome()方法是否存在注解
        if (dsMethod.isAnnotationPresent(MyAnnotation5.class)){
            //获取该注释对象
            MyAnnotation5 dsMethodAnnotation = dsMethod.getAnnotation(MyAnnotation5.class);

            System.out.println("用户的名字是:" + dsMethodAnnotation.name() + ",id是:" + dsMethodAnnotation.id());
        } else {
            System.out.println(t11Class.getSimpleName() + "的" + dsMethod.getName() + "没有MyAnnotation5的注释");
        }


        //对比试验,判断Test09类中的doSome()方法有无@MyAnnotation5注释
        Class<?> aClass = Class.forName("Day19注解.Test09");
        Method doSome = aClass.getMethod("doSome");
        if (doSome.isAnnotationPresent(MyAnnotation5.class)){
            MyAnnotation5 annotation = doSome.getAnnotation(MyAnnotation5.class);
            System.out.println("用户的名字是:" + annotation.name() + ",id是:" + annotation.id());

        } else {
            System.out.println(aClass.getSimpleName() + "的" + doSome.getName() + "没有MyAnnotation5的注释");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值