注解(Annotation)(2月27总结)

文章目录

相比较于注释:
     1,注解和注释都是为代码添加额外信息
     2,定义不同。注解是Java的一种数据类型,和class,接口具有同等地位
     3,作用不同。注解参与编译器,编译不过会报错
     4,使用位置不同。注解的使用位置有严格限制
     5,注释的作用层次仅在java文件层次,后续过程都不参与。但是注解可以参与。
AM 9:20注解定义
自定义注解格式
public @interface 注解名 { 
  	定义体
}

从形式上看,十分类似于接口定义,但它不是接口
和类,接口的地位类似,注解也是一种数据类型。
@必不可少
注解之间不能继承
AM 9:40注解使用
在这里插入代码片

1、定义年龄(18到25)\名字(最长5个字)注解: AgeBound、NameBound

//@Target元注解,注解可以作用的目标(整个类、构造方法、成员变量)
@Target({ElementType.TYPE,ElementType.CONSTRUCTOR,ElementType.FIELD})

AM 10:40更该注解的保留级别:为运行时(才能判断生效)
//@Retention元注解,来定义我们自己定义的注解的保留级别
@Retention(RetentionPolicy.RUNTIME)
public @interface AgeBound {
    // 定义2个属性值
    int ageMin();
    int ageMax();
}

再定义一个注解限制名字长度
//@Retention元注解,来定义我们自己定义的注解的保留级别
@Retention(RetentionPolicy.RUNTIME)
@interface NameBound {
    // 定义一个最大长度
    int nameLimit() default 5;
}
结果:
true
Student{age=20, name='张三'}
true
Exception in thread "main" java.lang.IllegalArgumentException: 名字不合法,长度为:8

2、写一个学生类: Student.java

类定义好了,注解定义好了,现在做一个注解处理器

3、专门用来生产student对象: StudentFactory.java

//注解的本质是一个标签:没有处理,现在通过StudentFactory这样一个注解处理器去处理
public class StudentFactory {

    通过无参的构造方法,将字节码对象传给studentCls
    private Class studentCls;
    public StudentFactory() {
        this.studentCls = Student.class;
    }

    //定义一个方法:专门用于获取学生对象
    public Student getStudent(int age, String name) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //满足需求:2和3
        // 2、age校验
        judgeAge(age);

        // 3、名字的校验
        judgeName(name);

        // 1、通过反射去实例化(返回一个学生对象)
        // 获取构造函数(参数为class类型,构造函数为2参)
        Constructor declaredConstructor =
                studentCls.getDeclaredConstructor(int.class, String.class);
        // 暴力方式(拿私有的构造方法去实例化没有权限)(忽略语法检查)
        declaredConstructor.setAccessible(true);
        Student student = (Student) declaredConstructor.newInstance(age, name);
        return student;
    }


//===========================================================================以下是被抽取的方法
	private void judgeName(String name) throws NoSuchFieldException {
        // 通过字节码文件对象获取年龄的成员变量
        Field nameField = studentCls.getDeclaredField("name");
        // 判断是否使用了注解
        boolean annotationPresent = nameField.isAnnotationPresent(NameBound.class);
        if (annotationPresent) {
            // 获取注解实例
            NameBound nameBound = nameField.getAnnotation(NameBound.class);
            // 获取具体的值
            int nameLimit = nameBound.nameLimit();
            //校验名字是否满足条件
            if (name.length() > nameLimit) {
                throw new IllegalArgumentException("名字不合法,长度为:" + name.length());
            }
        }
    }

    private void judgeAge(int age) throws NoSuchFieldException {
        Field ageField = studentCls.getDeclaredField("age");


        // 先去判断age成员变量是否使用了注解
        // isAnnotationPresent是判断是否使用了注解 参数是对应的注解类型的字节码文件对象
        boolean annotationPresent = ageField.isAnnotationPresent(AgeBound.class);
        System.out.println(annotationPresent);


        if (annotationPresent) {
            // 获取属性值
            // getAnnotation(AgeBound.class) 获取注解实例
            AgeBound ageBound = ageField.getAnnotation(AgeBound.class);
            // 获取(注解中)具体的值,拿到
            int ageMax = ageBound.ageMax();
            int ageMin = ageBound.ageMin();
            if (age < ageMin || age > ageMax) {
                throw new IllegalArgumentException("年龄不合法 :" + age);
            }

        }
    }
}

4、测试: Test.java

在这里插入代码片
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lacrimosa&L

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值