【问题标题】:Java weird compilation error with raw generic type parameter and Optionals带有原始泛型类型参数和 Optionals 的 Java 奇怪的编译错误
【发布时间】:2017-08-27 12:34:07
【问题描述】:

以下 Java 代码无法编译(使用 javac 1.8.0_121

import java.util.Optional;

class B<T> {}

public class Test {
    static B<Integer> f1(B<Object> a) { return null; }

    static B<Integer> f2() {
       Optional<B> opt = Optional.empty(); // note the raw type B
       return opt.map(Test::f1).get();
       // error: incompatible types: Object cannot be converted to B<Integer>
    }
}

我的问题是:为什么代码不能编译如上所述,如果我将f1 更改为原始类型,为什么它会编译:

static B<Integer> f1(B a) { return null; } // program compiles with raw B

我的猜测是opt.map 被推断为返回Optional&lt;Object&gt;(而不是Optional&lt;B&lt;Integer&gt;&gt;),但为什么呢?我已经研究了泛型和类型擦除(JLS 4.8)的其他问题,但它们都处理在原始类型本身上调用方法时的情况(例如this)。这里,opt 不是原始的,它只需要一个原始类型参数。另外,为什么第二个版本(参数a 是原始B 而不是B&lt;Object&gt;)有效?

编译错误信息

Error java: incompatible types: java.lang.Object cannot be converted to B&lt;java.lang.Integer&gt;

【问题讨论】:

  • 还能在这里添加编译错误信息吗?好吧,我错了,它在你的 cmets 里 :)
  • 你能澄清一下你所说的第一版和第二版吗?
  • 这个当然可以,因为它一开始就没有使用原始类型
  • Optional&lt;B&gt; integerB = opt.map(Test::f1); return integerB.get(); 这似乎也可以工作,而它的链式版本不工作return opt.map(Test::f1).get(); 很奇怪。
  • 看起来这是 java 8 中的一个合法错误,程序编译在 java 9 early access

标签: java generics optional raw-types


【解决方案1】:

使 f1 使用? extends Object,将通配符类型添加到B

import java.util.Optional;

class B<T> {}

public class Test {
   static B<Integer> f1(B<? extends Object> a) { return null; }

   static B<Integer> f2() {
       Optional<B<?>> opt = Optional.empty(); // note the raw type B
       return opt.map(x -> f1(x)).get();
    }
} 

【讨论】:

  • 编辑了问题以指定我的问题是为什么 original 代码无法编译。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-06
  • 2017-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多