混合方法引用和泛型时出现 LambdaConversionException
LambdaConversionException when mixing method reference and generics
下面的代码编译正常,但在运行时抛出异常。这是预期的行为吗?为什么?
代码:
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
即使您使用 lambda 表达式而不是方法引用,您的代码也不会工作,因为流已经耗尽
System.out.println(a.min());
System.out.println(a.max()); // exhausted
流是一次性的。但是让我们把这个分开。当您使用方法参考版本时,它捕获 Number
作为类型参数而不是 Comparable
其中 Number
没有 compareTo
maybe 因为 Number
在这里更具体。
如果你只使用 Comparable
它会很好
static class A<T extends Comparable<? super T>> {
Stream<T> s = Stream.empty();
public T min() { return s.min((t1, t2) -> t1.compareTo(t2)).orElse(null); }
public T max() {
T t = s.max(T::compareTo).orElse(null);
return t; }
}
System.out.println(a.max()); //null
IMO(谨慎起见):我认为这是一个错误。
我真正相信的是:这绝对是一个错误。
编辑: 事实证明,这实际上是一个错误,并且经 Brian Goetz 确认已修复。 https://bugs.openjdk.java.net/browse/JDK-8058112. According to the bug database, this was fixed in 8u40
调用站点初始化问题已通过 JDK-8058112 解决
在 JDK 8u40 b17 或更高版本中可用。
这似乎是 Netbeans 的问题,我无法在命令行中使用 javac 时重现该问题。我已经提交了 bug report.
对于那些在 2017 年遇到此问题 java8 1.8.0_141
的人,还有另一个已提交的错误报告 JDK-8142476,修复版本仅为 java9
。
下面的代码编译正常,但在运行时抛出异常。这是预期的行为吗?为什么?
代码:
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
即使您使用 lambda 表达式而不是方法引用,您的代码也不会工作,因为流已经耗尽
System.out.println(a.min());
System.out.println(a.max()); // exhausted
流是一次性的。但是让我们把这个分开。当您使用方法参考版本时,它捕获 Number
作为类型参数而不是 Comparable
其中 Number
没有 compareTo
maybe 因为 Number
在这里更具体。
如果你只使用 Comparable
它会很好
static class A<T extends Comparable<? super T>> {
Stream<T> s = Stream.empty();
public T min() { return s.min((t1, t2) -> t1.compareTo(t2)).orElse(null); }
public T max() {
T t = s.max(T::compareTo).orElse(null);
return t; }
}
System.out.println(a.max()); //null
IMO(谨慎起见):我认为这是一个错误。
我真正相信的是:这绝对是一个错误。
编辑: 事实证明,这实际上是一个错误,并且经 Brian Goetz 确认已修复。 https://bugs.openjdk.java.net/browse/JDK-8058112. According to the bug database, this was fixed in 8u40
调用站点初始化问题已通过 JDK-8058112 解决 在 JDK 8u40 b17 或更高版本中可用。
这似乎是 Netbeans 的问题,我无法在命令行中使用 javac 时重现该问题。我已经提交了 bug report.
对于那些在 2017 年遇到此问题 java8 1.8.0_141
的人,还有另一个已提交的错误报告 JDK-8142476,修复版本仅为 java9
。