我仍然无法处理 java 泛型系统中的一些极端情况。
我有这个方法(我只对签名感兴趣):
interface Extractor<RETURN_TYPE> {
public <U extends Enum<U>> RETURN_TYPE extractEnum(final Class<U> enumType);
}
(考虑一个接口(interface),其实现有时提取 EnumSet,有时实现提取 JComboBox 等)
我想用一个在运行时获得的类来调用它,所以我简单地这样调用它:
public static <RETURN_TYPE> RETURN_TYPE extractField(final Extractor<RETURN_TYPE> extractor, final Field field) {
final Class<?> type = field.getType();
if (type.isEnum())
return extractor.extractEnum(/* error here*/type.asSubclass(Enum.class));
throw new RuntimeException("the rest of the visitor is not necessary here");
}
然后我收到一条奇怪的错误消息: 不兼容的类型 发现:java.lang.Object 必需:RETURN_TYPE
消息的位置,如果就在调用的开始括号之后,类型的“t”之前。
如果我从非通用上下文中调用它,它会起作用:
Integer extractField(final Extractor<Integer> extractor, final Field field) {
final Class<?> type = field.getType();
if (type.isEnum())
return extractor.extractEnum(type.asSubclass(Enum.class));
throw new RuntimeException("the rest of the visitor is not necessary here");
}
有人对这个问题有解释和解决方案吗?
这里有一个完整的文件供想玩的人使用:
public class Blah {
interface Extractor<RETURN_TYPE> {
public <U extends Enum<U>> RETURN_TYPE extractEnum(final Class<U> enumType);
}
public static <RETURN_TYPE> RETURN_TYPE extractField(final Extractor<RETURN_TYPE> extractor, final Field field) {
final Class<?> type = field.getType();
if (type.isEnum())
return extractor.extractEnum(/* error here*/type.asSubclass(Enum.class));
throw new RuntimeException("the rest of the visitor is not necessary here");
}
public static Integer extractField(final Extractor<Integer> extractor, final Field field) {
final Class<?> type = field.getType();
if (type.isEnum())
return extractor.extractEnum(type.asSubclass(Enum.class));
throw new RuntimeException("the rest of the visitor is not necessary here");
}
}
提前致谢,
妮可
最佳答案
实际上,如果这是您的编译器中的错误,我不会感到惊讶。通过认真使用泛型(你正在做的事情,结合参数化方法、有界通配符和泛型的其他“高级”使用)我去年在 javac 中遇到了两三个问题(令人讨厌的是,同一个单元通常在 IDE 中编译良好)。
在你的情况下,我相当确定这是一个错误,因为编译器提示的部分是 extractor.extractEnum
正在返回 Object
而不是 RETURN_TYPE
.不管它对你的枚举方法参数做了什么疯狂的推断......它从类型签名中知道 Extractor 是一个 Extractor<RETURN_TYPE>
,所以你应该总是能够说return extractor.extractEnum(...);
.
该死的证据是,即使您使用 null
调用该方法参数(因此完全消除了参数中枚举泛型的任何潜在并发症),编译器仍然提示。特别是,它现在表示它认为 Extractor 的返回类型是 U<RETURN_TYPE>
这显然是垃圾。
一般来说,解决这些问题的方法是引入一些显式转换。如果将 extractEnum 的输出转换为 RETURN_TYPE,编译器是否满意? 编辑:不,它真的不是 - 它提示 U<RETURN_TYPE>
和 RETURN_TYPE
是不可转换的-eep...
如果您使用的是最新的 1.6 编译器,我建议您向 Sun 报告此问题,因为这是 javac 的一个大问题。下面是一个非常简短的测试用例:
public class Test {
interface Sub<O> {
public <I extends Enum<I>> O method(final Class<I> enumType);
}
public static <O> O go(final Sub<O> sub) {
return sub.method(null);
}
}
附言一般约定使用单个大写字母来指定泛型类型参数。我不会说“我是对的,你是错的”,但请记住,与使用 Extractor 相比,我发现你的代码更难阅读和遵循。 (从 Hemal 对他的回答的措辞来看,这对他来说也是一样的。)
关于java - java中的枚举和泛型方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1541410/