当你定义一个 Java 接口(interface)时,可以声明一个带有类型参数的方法,例如这样:
public interface ExampleInterface {
<E extends Enum<E>> Class<E> options();
}
同样的事情在注释中不起作用。例如,这是非法的:
public @interface ExampleAnnotation {
<E extends Enum<E>> Class<E> options();
}
我可以通过使用原始类型 Enum
得到我想要的:
public @interface ExampleAnnotation {
@SuppressWarnings("rawtypes")
Class<? extends Enum> options();
}
究竟是什么原因不能用类型参数声明注解属性?
最佳答案
我认为这是可能的,但它需要对语言规范进行大量添加,这是不合理的。
首先,对于您的枚举示例,您可以使用 Class<? extends Enum<?>> options
.
Class<? extends Enum> options
还有一个问题: 自 Enum.class
是 Class<Enum>
这是 Class<? extends Enum>
, options=Enum.class
是合法的
Class<? extends Enum<?>> options
不会发生这种情况, 因为 Enum
不是 Enum<?>
的子类型,在凌乱的原始类型处理中是一个相当偶然的事实。
回到一般问题。由于在有限的属性类型中,Class
是唯一一个有类型参数的,通配符通常足够表达,你的问题不是很值得解决。
让我们进一步概括这个问题,假设属性类型更多,而通配符在很多情况下都不够强大。例如,假设 Map
是允许的,例如
Map<String,Integer> options();
options={"a":1, "b":2} // suppose we have "map literal"
假设我们希望属性类型为 Map<x,x>
对于任何类型x
.这不能用通配符表示 - Map<?,?>
意思是Map<x,y>
对于任何 x,y
.
一种方法是允许类型的类型参数:<X>Map<X,X>
.一般来说,这实际上非常有用。但这是对类型系统的重大改变。
另一种方法是重新解释注释类型中方法的类型参数。
<X> Map<X,X> options();
options={ "a":"a", "b":"b" } // infer X=String
这在目前对方法类型参数、推理规则、继承规则等的理解中根本不起作用。我们需要更改/添加很多东西才能使其起作用。
在任何一种方法中,如何交付 X
都是一个问题。到注释处理器。我们必须发明一些额外的机制来为实例携带类型参数。
关于java - 带有类型参数的注解属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7594582/