JDK是甲骨文的JDK 1.8u65,但问题是"低至"1.8u25.
这是完整的SSCCE:
public final class Foo
{
private interface X
{
default void x()
{
}
}
private enum E1
implements X
{
INSTANCE,
;
}
private enum E2
implements X
{
INSTANCE,
;
}
public static void main(final String... args)
{
Stream.of(E1.INSTANCE, E2.INSTANCE).forEach(X::x);
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码编译; 但它在运行时失败:
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 com.github.fge.grappa.debugger.main.Foo.main(Foo.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.invoke.LambdaConversionException: …Run Code Online (Sandbox Code Playgroud) 我在使用jre1.8.0_66的代码运行中遇到这个奇怪的异常:
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 main
Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Object; not a subtype of implementation type interface Fruit
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)
... 3 more
Run Code Online (Sandbox Code Playgroud)
这是什么意思?代码如下:
public static interface Fruit {
int getPickingMonth();
}
public static class Apple implements Fruit, Serializable {
@Override
public int getPickingMonth() {
return 11;
}
}
public static class Orange implements Fruit, Serializable {
@Override
public int …Run Code Online (Sandbox Code Playgroud) 在交集类型中将方法引用应用于第二种类型时,我遇到了一个非常奇怪的问题.这是一个最小的测试用例:
class LambdaTest {
interface A {}
interface B {
B doIt();
}
static class AB implements A, B {
public B doIt() {
return this;
}
}
static <E extends A & B> void run(E e) {
Collections.singleton(e).stream().map(B::doIt);
}
public static void main(String[] args) {
run(new AB());
}
}
Run Code Online (Sandbox Code Playgroud)
此代码编译但run在运行时失败并出现错误:
java.lang.invoke.LambdaConversionException:无效的接收器类型接口LambdaTest $ A; 不是实现类型接口LambdaTest $ B的子类型
显式指定lambda的类型时甚至会发生此问题:
static <E extends A & B> void run(E e) {
final Function<E, B> doIt = B::doIt;
Collections.singleton(e).stream().map(doIt);
} …Run Code Online (Sandbox Code Playgroud) 下面的代码编译正常但在运行时抛出异常.这是预期的行为吗?为什么?
码:
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); }
}
Run Code Online (Sandbox Code Playgroud)
输出:
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 …Run Code Online (Sandbox Code Playgroud) 我曾经把java方法引用看作是一个语法糖,它是作为lambda表达式的一个补充而引入的.但显然事实并非如此.
在下面的示例中,与lambda表达式不同,方法引用会产生错误.
有人可以解释一下奇怪的行为吗?
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
System.out.println(getMapUsingLanmdaApproach(MyEnum.class)); // works as expected: {1=A, 2=B}
System.out.println(getMapUsingMethodReferenceApproach(MyEnum.class)); // throws java.lang.BootstrapMethodError
}
static <K, V extends Enum<?> & HasProperty<K>> Map<K, V> getMapUsingLanmdaApproach(Class<V> aClass) {
return Stream.of(aClass.getEnumConstants())
.collect(Collectors.toMap(e -> e.getProperty(), Function.identity()));
}
static <K, V extends Enum<?> & HasProperty<K>> Map<K, V> getMapUsingMethodReferenceApproach(Class<V> aClass) {
return Stream.of(aClass.getEnumConstants())
.collect(Collectors.toMap(HasProperty::getProperty, Function.identity()));
}
}
enum MyEnum implements HasProperty<Integer> {
A(1),
B(2);
private final Integer …Run Code Online (Sandbox Code Playgroud) I am encountering a persistent problem when obfuscating java8 source code. Lambda method references seem to fail at runtime when they are used multiple times within a function. The failing code:
Set<String> roleNames = this.userDAO.getUserRoles(userDTO.getId()).stream().map(RoleDTO::getName).collect(Collectors.toSet());
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(roleNames);
Set<String> permissions = this.userDAO.getUserPermissions(userDTO.getId()).stream().map(NameDescriptionDTO::getName).collect(Collectors.toSet());
authorizationInfo.addStringPermissions(permissions);
Run Code Online (Sandbox Code Playgroud)
This works fine when compiling with maven and java 8.0_40, however this fails when proguard has obfuscated the lib with the following stack trace:
org.jboss.weld.interceptor.proxy.InterceptorException: java.lang.BootstrapMethodError: call site initialization exception
~
Caused by: java.lang.invoke.LambdaConversionException: Invalid …Run Code Online (Sandbox Code Playgroud) 我想加入一个名单:
List<String> names;
names = books.stream()
.map( b -> b.getName() )
.filter( n -> ( (n != null) && (!n.isEmpty()) ) )
.collect(Collectors.joining(", "));
Run Code Online (Sandbox Code Playgroud)
这不会编译说:
不兼容的类型.推理变量R具有不兼容的边界
所以经过一些研究,似乎有些东西我误解了.我认为.map( b -> b.getName() )返回/将类型更改为String,似乎有些错误.如果我使用.map(Book::getName),我仍然会收到错误,但我可能并不完全理解其中的差异.
但是,这不抱怨:
List<String> names;
names = books.stream()
.map( b -> b.getName() )
.map( Book::getName )
.filter( n -> ( (n != null) && (!n.isEmpty()) ) )
.collect(Collectors.joining(", "));
Run Code Online (Sandbox Code Playgroud)
有人能解释一下为什么吗?关于它们之间的差异的一些教学解释.map( b -> b.getName() )也.map(Book::getName)被赞赏,因为我认为我没有做对.