Inherited和Repeatable元注解组合使用

Inherited和Repeatable元注解组合使用

在使用Repeatable元注解后,我们会发现父类上使用Value注解标记同样也是不能获取到注解属性值,那么我们此时会有一个疑问,如何在父类上使用注解同样能在子类中获取注解属性内容呢?此时我们可能会联想到Inherited元注解,那么我们开始尝试下我们的猜想!

基础类准备:

Value注解类

@Repeatable(Values.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
    String value();
}

Values注解类

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Values {
    Value[] value();
}

Parent类

@Value(value = "parent-1")
@Value(value = "parent-2")
public class Parent {
}

Child类

@Value(value = "child-1")
@Value(value = "child-2")
public class Child extends Parent {
}

测试类

public class AnnoMain {
​
    public static void main(String[] args) {
        Class<Child> clazz = Child.class;
        if (clazz.isAnnotationPresent(Value.class)) {
            Value valueAnnotation = clazz.getAnnotation(Value.class);
            System.out.println("Value annotation present: " + valueAnnotation.value());
        }
        if (clazz.isAnnotationPresent(Values.class)) {
            System.out.print("Values annotation present: ");
            Values dataAnnotation = clazz.getAnnotation(Values.class);
            Value[] values = dataAnnotation.value();
            for (Value value : values) {
                System.out.print(value.value() + "\t");
            }
        }
    }
}

我们首先对Value注解类添加@Inherited元注解,代码如下:

@Inherited
@Repeatable(Values.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
    String value();
}

此时我们会看到在IDE编译器中会有报错提示,如下所示:

此处提示我们在容器注解中不存在必要的@Inherited注解,因此我们在Values注解中也加入@Inherited注解

那么如果我们仅在Values注解中添加@Inherited注解,不在Value注解中添加@Inherited注解会有什么问题呢?

我们先将Value注解恢复原状,代码如下:

@Repeatable(Values.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
    String value();
}

再在Values注解中添加@Inherited注解,代码如下:

@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Values {
    Value[] value();
}

此时没有任何的错误信息,那么我们开始调整下Child类信息,再编写一个测试类:

public class Child extends Parent {
}

执行测试类,结果如下:

我们会发现,同样父类的多标记内容也全部被打印出来了,那么如果在子类上也添加同多次标记,是否也会像单个标记的情况一样覆盖掉呢?那么接下来我们修改下Child类

@Value(value = "child-1")
@Value(value = "child-2")
public class Child extends Parent {
}

执行测试类,结果如下:

我们会发现,这种容器注解,也跟单次标记的注解一样会覆盖掉父类数据。

那么如果我们父类和子类多次标记个数不一致的情况下,执行出来的结果又会是什么样子呢?我们来修改下Parent类,Child类还是使用基础类,代码如下:

@Value(value = "parent-1")
@Value(value = "parent-2")
@Value(value = "parent-3")
public class Parent {
}

执行测试类,结果如下:

我们可以明显看出,多次标记的情况下,不管父类添加多少标记,子类的多次标记都会将父类的多次标记内容覆盖掉。

那么如果一个使用单次标记,一个使用多次标记会是什么样子的呢?

我们来修改下Child和Parent类,代码如下:

Child类

@Value(value = "child-1")
public class Child extends Parent {
}

Parent类

@Value(value = "parent-1")
@Value(value = "parent-2")
@Value(value = "parent-3")
public class Parent {
}

执行测试类,结果如下:

我们从结果可以看出,一次跟多次标记会全部都输出,也就是说父子类要么都是一次标记,要么都是多次标记,子类才会将注解内容覆盖掉!

接下来,我们做另一个猜想,容器注解Values使用@Inherited注解,但是Value注解不使用@Inherited注解,是否会影响到单次标记的注解呢?

那么我们修改下Parent和Child类,代码如下:

public class Child extends Parent {
}
​
@Value(value = "parent-1")
public class Parent {
}

执行测试类,结果如下:

我们会发现,子类并没有办法获取到父类的注解属性内容,也就说容器注解的继承并不会影响到容器注解关联的注解。那么我们再在Value注解上添加@Inherited注解。

修改Value注解,代码如下:

@Inherited
@Repeatable(Values.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
    String value();
}

执行测试类,结果如下:

我们可以从这些执行结果中看出,Value添加@Inherited注解,Values容器注解不添加@Inherited注解,容器注解会受到影响,编译不通过,反之则正常,但是单次标记不会继承父类的注解信息内容。

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

风之殇2016

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

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

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

打赏作者

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

抵扣说明:

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

余额充值