为什么java类不从已实现的接口继承注释?

时间:2022-05-20 07:00:59

I've been using Guice's AOP to intercept some method calls. My class implements an interface and I would like to annotate the interface methods so Guice could select the right methods. Even if the annotation type is annotated with Inherited annotation implementing class doesn't inherit the annotation as stated in Inherited's java doc:

我一直在使用Guice的AOP拦截一些方法调用。我的类实现了一个接口,我想注释接口方法,以便Guice可以选择正确的方法。即使注释类型使用Inherited annotation注释,实现类也不会继承Inherited的java doc中所述的注释:

Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

另请注意,此元注释仅导致注释从超类继承;已实现接口上的注释无效。

What could be the reason for this? Getting to know all interfaces that an object's class does implement in runtime is not that hard thing to do so there must be a good reason behind this decision.

这可能是什么原因?了解对象类在运行时实现的所有接口并不是一件难事,因此必须有充分的理由支持这一决定。

2 个解决方案

#1


115  

I'd say the reason is that otherwise a multiple-inheritance problem would occur.

我会说原因是否则会出现多重继承问题。

Example:

例:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Inherited
public @interface Baz { String value(); }

public interface Foo{
    @Baz("baz") void doStuff();
}

public interface Bar{
    @Baz("phleem") void doStuff();
}

public class Flipp{
    @Baz("flopp") public void doStuff(){}
}

public class MyClass extends Flipp implements Foo, Bar{}

If I do this:

如果我这样做:

MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value()

what's the result going to be? 'baz', 'phleem' or 'flopp'?

结果会是什么? 'baz','phleem'或'flopp'?


For this reason, annotations on interfaces are rarely useful.

因此,接口上的注释很少有用。

#2


32  

From the Javadoc for @Inherited:

来自@Inherited的Javadoc:

Indicates that an annotation type is automatically inherited. If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type. This process will be repeated until an annotation for this type is found, or the top of the class hierarchy (Object) is reached. If no superclass has an annotation for this type, then the query will indicate that the class in question has no such annotation. Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

表示自动继承注释类型。如果注释类型声明中存在Inherited元注释,并且用户在类声明上查询注释类型,并且类声明没有此类型的注释,则将自动查询类的超类以获取注释类型。将重复此过程,直到找到此类型的注释,或者到达类层次结构(对象)的顶部。如果没有超类具有此类型的注释,则查询将指示相关类没有此类注释。请注意,如果使用带注释的类型来注释除类之外的任何内容,则此元注释类型不起作用。另请注意,此元注释仅导致注释从超类继承;已实现接口上的注释无效。

On the other hand, JSR 305 validators do some sort of inheritance lookup. If you have a hierarchy of classes:

另一方面,JSR 305验证器执行某种继承查找。如果您有类的层次结构:

//Person.java
@Nonnull
 public Integer getAge() {...}

//Student.java (inherits from Person)
@Min(5)
public Integer getAge() {...}

Then the effective validations on Student.getAge() are @Nonnull @Min(5). @Nonnull has no @Inherited meta-annotation.

然后,Student.getAge()的有效验证是@Nonnull @Min(5)。 @Nonnull没有@Inherited元注释。

#1


115  

I'd say the reason is that otherwise a multiple-inheritance problem would occur.

我会说原因是否则会出现多重继承问题。

Example:

例:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Inherited
public @interface Baz { String value(); }

public interface Foo{
    @Baz("baz") void doStuff();
}

public interface Bar{
    @Baz("phleem") void doStuff();
}

public class Flipp{
    @Baz("flopp") public void doStuff(){}
}

public class MyClass extends Flipp implements Foo, Bar{}

If I do this:

如果我这样做:

MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value()

what's the result going to be? 'baz', 'phleem' or 'flopp'?

结果会是什么? 'baz','phleem'或'flopp'?


For this reason, annotations on interfaces are rarely useful.

因此,接口上的注释很少有用。

#2


32  

From the Javadoc for @Inherited:

来自@Inherited的Javadoc:

Indicates that an annotation type is automatically inherited. If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type. This process will be repeated until an annotation for this type is found, or the top of the class hierarchy (Object) is reached. If no superclass has an annotation for this type, then the query will indicate that the class in question has no such annotation. Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

表示自动继承注释类型。如果注释类型声明中存在Inherited元注释,并且用户在类声明上查询注释类型,并且类声明没有此类型的注释,则将自动查询类的超类以获取注释类型。将重复此过程,直到找到此类型的注释,或者到达类层次结构(对象)的顶部。如果没有超类具有此类型的注释,则查询将指示相关类没有此类注释。请注意,如果使用带注释的类型来注释除类之外的任何内容,则此元注释类型不起作用。另请注意,此元注释仅导致注释从超类继承;已实现接口上的注释无效。

On the other hand, JSR 305 validators do some sort of inheritance lookup. If you have a hierarchy of classes:

另一方面,JSR 305验证器执行某种继承查找。如果您有类的层次结构:

//Person.java
@Nonnull
 public Integer getAge() {...}

//Student.java (inherits from Person)
@Min(5)
public Integer getAge() {...}

Then the effective validations on Student.getAge() are @Nonnull @Min(5). @Nonnull has no @Inherited meta-annotation.

然后,Student.getAge()的有效验证是@Nonnull @Min(5)。 @Nonnull没有@Inherited元注释。