java - java中的枚举和泛型方法

标签 java generics enums crtp

我仍然无法处理 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/

相关文章:

java - 第三个数组的元素的数组和

java - 重写方法中的泛型

java - 使用通用枚举类型扩展抽象类

c# - 设计模式 : Polymorphism for list of objects

java - 如果在 Raspbian 中运行,请停止 Java 进程

java - memcache究竟是如何清除过期数据的?

java - 为什么静态泛型方法的返回类型前面应该有<T>

基于泛型参数的java泛型类型推断

ios - 通用 RawRepresentable 协议(protocol)属性

swift - 在 Swift 中,为什么 CodingKey 是我看到的与枚举一起使用的协议(protocol),用于在结构上使用 Codable 协议(protocol)?