混合方法引用和泛型时的LambdaConversionException

时间:2015-11-03 19:26:28

标签: java generics java-8 method-reference

下面的代码编译正常但在运行时抛出异常。这是预期的行为吗?为什么?

代码:

public static void main(String[] args) {
  A<Integer> a = new A<> ();
  System.out.println(a.min()); //prints null as expected
  System.out.println(a.max()); //throws exception
}

static class A<T extends Number & Comparable<? super T>> {
  Stream<T> s = Stream.empty();
  public T min() { return s.min((t1, t2) -> t1.compareTo(t2)).orElse(null); }
  public T max() { return s.max(T::compareTo).orElse(null); }
}

输出:

null
Exception in thread "main" java.lang.BootstrapMethodError: call site initialization exception
    at java.lang.invoke.CallSite.makeSite(CallSite.java:341)
    at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
    at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
    at abc$A.max(abc.java:19)
    at abc.main(abc.java:8)
Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Number; not a subtype of implementation type interface java.lang.Comparable
    at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233)
    at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
    at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
    ... 4 more

4 个答案:

答案 0 :(得分:6)

即使您使用lambdas而不是方法引用,您的代码仍然无效,因为流已经用尽

 System.out.println(a.min()); 
 System.out.println(a.max()); // exhausted

Streams是一次性的。但是让我们分开吧。当您使用方法参考版本时,它会将Number作为类型参数捕获而不是Comparable Number没有compareTo 可能,因为{ {1}}在这里更具体。 如果您只使用Number,它将正常工作

Comparable

IMO(只是为了谨慎):我认为这是一个错误。

我真正相信:这绝对是一个错误。

编辑:事实证明,这实际上是一个错误,并且已由Brian Goetz确认修复。 https://bugs.openjdk.java.net/browse/JDK-8058112。根据错误数据库,这已在8u40

中修复

答案 1 :(得分:4)

通过JDK-8058112解决了呼叫网站初始化问题 可在JDK 8u40 b17或更高版本中使用。

答案 2 :(得分:2)

这似乎是一个Netbeans问题,我无法在命令行中使用javac时重现该问题。我已经提交了bug report

答案 3 :(得分:2)

对于那些在2017年使用java8 1.8.0_141面临此问题的人,还有其他提交的错误报告JDK-8142476,修复版本仅为java9