Java 注解(Annotation)

一、基础

  • 作用

    • 通过反射技术去得到类中的注解,以决定如何运行类
  • 定义

    • 注解(注释类型)是一种引用数据类型,是代码中的特殊标记,用于替代配置文件,决定类如何运行,编译之后生成xxx.class文件

    • 自定义注解语法格式:[修饰符列表] @interface 注解类型名{ }

    • public @interface AnnotationTest {}
      
  • 用法

    1. 注解使用时语法格式为:@注解类型名
    2. 注解可以出现在类上、方法上、变量上(前)、注解类上、接口上等几乎任何地方
  • 元注解(meta-annotation):用于对注解类型进行注解的注解类,常用元注解如下

    • @Target:描述注解的使用范围(位置)
      • @Target(ElementType.METHOD)只对方法生效
    • @Retention:描述注解保留的范围(最终保存在哪个阶段)
      • @Retention(RentationPolicy.SOURCE)表示该注解只被保留在java源文件中
      • @Retention(RentationPolicy.CLASS) 表示该注解被保存在class文件中
      • @Retention(RentationPolicy.RUNTIME)表示该注解被保存在class文件中,并且可以被反射机制所读取到
    • @Documented:描述使用javadoc工具类生成帮助文档时是否需要保留其注解信息
    • @Inherit:使被它修饰的注解具有继承性(若一个类使用@Inherit修饰的注解,其子类自动具有该注解)

二、JDK内置注解

  • @Deprecated 表明此方法已废弃、暂时可用,但后续不会更新、可能删除,建议不要调用此方法,有更好的解决方案
    • 元注解:@Documented、@Retention(RetentionPolicy.RUNTIME)、@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
    • 该注解保存在字节码文件中,并且可以被反射机制所读取
    • 该注解可放置在Retention所标识之处
  • @Override 重写方法
    • 元注解:@Target(ElementType.METHOD)、@Retention(RetentionPolicy.SOURCE)
    • 这个注解只能注解方法
    • 标识性注解,编译阶段供编译器参考,与运行阶段无关
    • 带有该注解的方法,编译器会进行编译检查是否为重写父类方法,否则报错
  • @SuppressWarnings 告诉编译器忽略指定(未指定泛型、未使用和过时)的警告,不用在编译完成后出现警告信息

三、注解中的属性

  • 注解当中可以定义属性,看似方法,称为属性
    • 若属性有指定默认值,则使用注解时括号中可以不写该值
//自定义注解代码
public @interface AnnotationTest {  
    String name();
  	String color();
  	//属性指定默认值
  	int age() default 25;
  	String[] email();
}
//测试方法中的代码
public class Test {
    //@AnnotationTest(属性名=属性值)
  	//指定了默认属性后,括号中可以不写
    @AnnotationTest(name="abc",color="red",email={"abc@qq.com","abc@163.com"})//若数组中只有一个元素,则可省略大括号
    public void test(){
    }
}
  • ​ 若注解定义中属性只有一个且属性名为value,则在注解使用时,可以不写属性名和"=",直接填写属性值
//自定义注解代码
public @interface AnnotationTest {
    String value();
}
//测试方法中的代码
public class Test {
    @AnnotationTest("hello")
    public void test(){
    }
}
  • 属性类型:byte、short、int、long、float、double、boolean、char、String、Class、枚举类型以及前面每一种的数组形式

四、反射注解

//自定义注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest {
    String value() default "abc";
}
//使用了该自定义注解的类
@AnnotationTest("hello")
public class User {
    public int no;
}
//测试类
//若AnnotationTest处于不同包下,则需要导包
public static void main(String[] args) throws Exception{
        //获取使用了注解的那个类,若是类中的方法或属性用了注解,则还需要进一步取得类中的方法或属性
        Class c = Class.forName("bean.User");

        //判断类上面是否有@AnnotationTest
        if ( c.isAnnotationPresent(AnnotationTest.class)) {  //true
            //获取该注解对象,此处使用了强制类型转换
            AnnotationTest annotationTest = (AnnotationTest)c.getAnnotation(AnnotationTest.class);
            //获取注解对象的属性,与调用接口相似
            String value = annotationTest.value();
        }
}

五、注解审查例子

  • 注解在程序当中等同于一种标记,一种自己设定规则。
  • 需求:被@Id注解的类中必须含有int类型的id属性
//自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
}
//自定义实体类
@Id()
public class User {
    public int id;
}
//自定义异常
public class HasNotIdPropertyException extends RuntimeException{
  	//需要写两个构造方法,抛出异常信息
    public HasNotIdPropertyException() {
    }

    public HasNotIdPropertyException(String message) {
        super(message);
    }
}
//测试类
//测试方法中的代码
public class Test {
    public static void main(String[] args) throws Exception{

        //获取使用了注解的那个类
        Class c = Class.forName("bean.User");
        //判断类上是否存在Id注解
        if(c.isAnnotationPresent(Id.class)){
            //当一个类上面有@Id注解的时候,要求类中必须存在int类型的id属性
            //如果没有int类型的id属性则报异常
            Field[] fields = c.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("被@Id注解标注的类中必须有一个int类型的id属性");
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值