繁体   English   中英

@Inherited注释未被继承

[英]@Inherited annotation is not being inherited

我有一个SubClass和一个SuperClass ,以及一个DocAnnotation注释。 我需要调用SubClass.foo()才能从SubClassSuperClass获得所有类注释。 这些类的定义如下:

超类

package Code

import Annotations.DocAnnotation;
import java.util.Arrays;

@DocAnnotation("Super Annotation")
public class SuperClass {

    public void foo() {
        System.out.println(Arrays.toString(this.getClass().getAnnotations()));
        System.out.println(Arrays.toString(this.getClass().getDeclaredAnnotations()));
    }
}

子类

package Code;

import Annotations.DocAnnotation;

@DocAnnotation("Sub Annotation")
public class SubClass extends SuperClass{
}

DocAnnotation

package Annotations;

import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(DocAnnotations.class)
public @interface DocAnnotation {
    String value();
}

运行SubClass.foo,我希望同时看到"Super Annotation""Sub Annotation"但我只会看到[@Annotations.DocAnnotation(value=Sub Annotation)] 我是误解了@inherited的作用,还是做错了什么?


编辑:

添加注释后@DocAnnotation("Super Annotation")SubClass (这是同一作为SuperClass ),它实际上表明了两次,一次是其在使用SubClass ,一旦其在使用SuperClass 现在我几乎可以肯定我误会了...

您注释错误。 Javadoc明确指出:

指示注释类型是自动继承的。 如果注释类型声明中存在继承的元注释,并且用户在类声明中查询了注释类型,并且该类声明没有该类型的注释,则将自动查询该类的超类以获取注释类型。

换句话说:如果查询子类,那么您将发现被注释的超类 但是,这并不是 “ OO含义”中的继承 如果要同时看到两个注释,则必须编写代码以手动检查类继承树中的每个类。

这似乎是预期的行为,或者至少已指定以这种方式工作( doc ):

如果用户在类声明中查询注释类型, 并且该类声明没有该类型的注释,则将自动查询该类的超类以获取注释类型。

换句话说,由于SubClass已经使用@DocAnnotation了注释, @DocAnnotation不会查询超类。

但是,在进一步检查中,该行为似乎有些奇怪,尤其是在尝试使用包含注释类型的存在之后。 我想出了以下示例来说明这一点( link ):

import java.lang.annotation.*;
import java.util.*;

@Inherited
@Repeatable(Container.class)
@Retention(RetentionPolicy.RUNTIME)
@interface Ann {
    String value();
}

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface Container {
    Ann[] value();
}

// Basic case. Result is that
// only @Ann("2") is present on
// ExhibitASub.
@Ann("1")
class ExhibitASuper {
}
@Ann("2")
class ExhibitASub extends ExhibitASuper {
}

// Because this case results in the
// @Container being present on ExhibitBSuper,
// rather than @Ann, all three annotations
// end up appearing on ExhibitBSub.
@Ann("1")
@Ann("2")
class ExhibitBSuper {
}
@Ann("3")
class ExhibitBSub extends ExhibitBSuper {
}

// Similar to the preceding case, by
// forcing the use of @Container, both
// annotations are present on ExhibitCSub.
@Container(@Ann("1"))
class ExhibitCSuper {
}
@Ann("2")
class ExhibitCSub extends ExhibitCSuper {
}

// Yet when we force both to use @Container,
// only @Container(@Ann("2")) is present on
// ExhibitDSub.
@Container(@Ann("1"))
class ExhibitDSuper {
}
@Container(@Ann("2"))
class ExhibitDSub extends ExhibitDSuper {
}

class Main {
    public static void main(String[] args) {
        for (Class<?> cls : Arrays.asList(ExhibitASub.class,
                                          ExhibitBSub.class,
                                          ExhibitCSub.class,
                                          ExhibitDSub.class)) {
            System.out.printf("%s:%n", cls);
            for (Annotation ann : cls.getAnnotations()) {
                System.out.printf("    %s%n", ann);
            }

            System.out.println();
        }
    }
}

输出如下:

class ExhibitASub:
    @Ann(value=2)

class ExhibitBSub:
    @Container(value=[@Ann(value=1), @Ann(value=2)])
    @Ann(value=3)

class ExhibitCSub:
    @Container(value=[@Ann(value=1)])
    @Ann(value=2)

class ExhibitDSub:
    @Container(value=[@Ann(value=2)])

请注意,对于B和C,我们同时在超类和子类上看到注释。 大概是因为(从严格意义上来说)超类上存在的注释与子类上存在的注释具有不同的类型。 请注意,对于D,我们返回仅看到子类注释,因为这两个类都使用容器类型。

在某些情况下,显式使用包含批注类型可能是一种解决方法,但是由于情况D,它不是通用解决方案。

我明天可能会为此提交错误报告,因为这似乎非常不可取。 由于@Inherited早于@Repeatable ,因此此行为可能来自以前的版本,在这种情况下不会发生这种情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM