【问题标题】:javac error: inconvertible types with generics?javac错误:具有泛型的不可转换类型?
【发布时间】:2011-06-17 07:20:45
【问题描述】:

还有其他几个 SO 问题谈论泛型编译 OK w/Eclipse 的编译器而不是 javac(即Java: Generics handled differenlty in Eclipse and javacGenerics compiles and runs in Eclipse, but doesn't compile in javac)——但这看起来有点不同。

我有一个enum 类:

public class LogEvent {
   public enum Type {
       // ... values here ...
   }
   ...
}

我还有另一个类,它的方法接收来自Enum 的任意类型的对象:

@Override public <E extends Enum<E>> void postEvent(
    Context context, E code, Object additionalData) 
{
    if (code instanceof LogEvent.Type)
    {
        LogEvent.Type scode = (LogEvent.Type)code;
    ...

这在 Eclipse 中运行良好,但是当我使用 ant 进行清理构建时,出现一对错误,一个在 instanceof 行,另一个在铸造行:

443: inconvertible types
    [javac] found   : E
    [javac] required: mypackage.LogEvent.Type
    [javac]         if (code instanceof LogEvent.Type)
    [javac]             ^

445: inconvertible types
    [javac] found   : E
    [javac] required: com.dekaresearch.tools.espdf.LogEvent.Type
    [javac]             LogEvent.Type scode = (LogEvent.Type)code;
    [javac]                                                  ^

为什么会发生这种情况,我怎样才能解决这个问题以便正确编译?

【问题讨论】:

    标签: java generics compiler-errors javac


    【解决方案1】:

    我遇到了类似的问题,从 jdk1.6.0_16 升级到 jdk1.6.0_23,它就消失了,没有任何代码更改。

    【讨论】:

      【解决方案2】:

      可能是因为您将 E 声明为扩展 Enum 的东西。我不能说我完全理解它,但它似乎将类型集限制为某些由于某种原因不能包含 LogEvent.Type 的子集。或者也许这只是编译器中的一个错误。如果有人能更清楚地解释它,我会很高兴,但您可以这样做:

      public <E extends Enum<?>> void postEvent(E code) 
      {
          if (code instanceof LogEvent.Type)
          {
              LogEvent.Type scode = (LogEvent.Type)code;
              ...
          }
          ...
      

      这很有效,而且比仅仅转换为一个对象更优雅。

      【讨论】:

      • 之所以有效,是因为“E extends Enum”指的是 Enum 的某些特定子类(可能与 LogEvent.Type 不兼容)。而“E extends Enum>”指的是任何扩展 Enum 的类,其中 LogEvent.Type 是一个有效的可能性。
      • @jtahlborn:E extends Enum&lt;E&gt; 是任何适当扩展 Enum 的类的标准样板文件,所有 enum 类都这样做,LogEvent.Type 是一个 enum 类,所以它应该作为好吧,但javac 中似乎有一个错误。
      • @jtahlborn,是的,想想看 - LogEvent.Type 是否扩展 Enum?确实如此。但这正是我们写“E extends Enum”时的意思,E = LogEvent.Type。所以我同意它看起来像 javac 中的一个错误。事实上,"E extends Enum>" 和 "E extends Enum" 应该是完全一样的意思,因为任何枚举类型 E 只能扩展 Enum 而不能。
      【解决方案3】:

      为了使用instanceof,两个操作数必须继承/实现相同的类/接口。
      E 只是不能转换为 LogEvent.Type

      我不知道您的完整方法是什么样的,但这应该通过使用接口而不是泛型来解决您的问题。

      public interface EventType { }
      public class LogEvent  {
          public enum Type implements EventType {}
      }
      
      public void postEvent(Context context, EventType code, Object additionalData) {
          if(code instanceof LogEvent.Type) {
          }
      }
      

      【讨论】:

      • 但我希望 Enum 成为基本类型,而不是 EventType。我需要我的方法来接受任意 Enum 值。
      • 但是为什么不能将 E 转换为 LogEvent.Type? E 是 Enum 的子类,LogEvent.Type 也是 Enum 的子类。我知道问题在于它不仅仅是 Enum,而是 Enum,我只是无法理解这到底是什么意思。
      • 关于这个主题的其他 SO 问题似乎表明 javac 有一个递归通用边界的已知错误,所以它可能会混淆。关于&lt;E extends Enum&lt;E&gt;&gt;,如果你之前没见过:angelikalanger.com/GenericsFAQ/FAQSections/…
      【解决方案4】:

      我不知道为什么会这样,但解决方法很简单:

      @Override public <E extends Enum<E>> void postEvent(
          Context context, E code, Object additionalData) 
      {
          Object tmp = code;
          if (tmp instanceof LogEvent.Type)
          {
              LogEvent.Type scode = (LogEvent.Type)tmp;
          ...
      

      它很丑,但它有效......

      【讨论】:

      • 谢谢。为什么这么丑?它简单且运行时成本低。
      • @Jason S:这很难看,因为我不明白为什么需要它。
      • 这是一个已知的错误,IIRC。实际上,有几十个相关的错误尚未修复。
      • 我正要把自己扔出窗外(嘿,我在一楼 :) 非常感谢这个……最糟糕的我想我已经为此而奋斗了几年前
      • 我认为这是错误(或其中之一):bugs.sun.com/view_bug.do?bug_id=6932571
      猜你喜欢
      • 2012-10-02
      • 1970-01-01
      • 2020-08-26
      • 1970-01-01
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 2018-06-11
      • 1970-01-01
      相关资源
      最近更新 更多