相关疑难解决方法(0)

枚举,接口和(Java 8)lambdas:代码编译但在运行时失败; 这是预期的吗?

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)

java type-inference java-8

21
推荐指数
1
解决办法
1303
查看次数

奇怪的例外"无效的接收器类型类java.lang.Object;不是...的子类型"

我在使用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)

java java-8 java-stream

13
推荐指数
1
解决办法
2912
查看次数

lambda上的LambdaConversionException在交集类型中采用第二种类型

在交集类型中将方法引用应用于第二种类型时,我遇到了一个非常奇怪的问题.这是一个最小的测试用例:

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)

java lambda java-8

10
推荐指数
0
解决办法
93
查看次数

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

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

码:

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 generics java-8 method-reference

9
推荐指数
2
解决办法
655
查看次数

为什么方法引用会产生java.lang.BootstrapMethodError

我曾经把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)

java generics lambda java-stream method-reference

7
推荐指数
0
解决办法
104
查看次数

Proguard obfuscation of Java8 method references breaks at runtime

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)

proguard java-8

3
推荐指数
1
解决办法
1348
查看次数

通过流加入字符串

我想加入一个名单:

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)被赞赏,因为我认为我没有做对.

java-8

3
推荐指数
1
解决办法
457
查看次数