gpt4 book ai didi

java - LambdaConversionException 与泛型 : JVM bug?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:02:28 26 4
gpt4 key购买 nike

我有一些带有方法引用的代码,编译正常但在运行时失败。

异常(exception)是这样的:

Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class redacted.BasicEntity; not a subtype of implementation type interface redacted.HasImagesEntity
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:289)

触发异常的类:

class ImageController<E extends BasicEntity & HasImagesEntity> {
void doTheThing(E entity) {
Set<String> filenames = entity.getImages().keySet().stream()
.map(entity::filename)
.collect(Collectors.toSet());
}
}

尝试解析 entity::filename 时抛出异常。 filename()HasImagesEntity 中声明。据我所知,我得到了异常,因为 E 的删除是 BasicEntity 并且 JVM 没有(不能?)考虑 E 上的其他边界。

当我将方法引用重写为普通 lambda 时,一切都很好。对我来说,一个构造按预期工作并且它的语义等价物爆炸了,这似乎真的很可疑。

这可能在规范中吗?我正在非常努力地寻找一种方法,使这不会成为编译器或运行时的问题,但还没有想出任何办法。

最佳答案

这是一个重现问题并仅使用核心 Java 类的简化示例:

public static void main(String[] argv) {
System.out.println(dummy("foo"));
}
static <T extends Serializable&CharSequence> int dummy(T value) {
return Optional.ofNullable(value).map(CharSequence::length).orElse(0);
}

您的假设是正确的,特定于 JRE 的实现接收目标方法作为 MethodHandle它没有关于泛型类型的信息。因此,它唯一看到的是原始类型不匹配。

与许多通用构造一样,字节码级别需要进行类型转换,但源代码中并未出现。自 LambdaMetafactory显式需要直接方法句柄,封装此类类型转换的方法引用不能作为MethodHandle传递给工厂。

有两种可能的处理方式。

第一个解决方案是更改 LambdaMetafactory 以信任 MethodHandle 如果接收器类型是 interface 并插入所需的类型转换本身在生成的 lambda 类中,而不是拒绝它。毕竟,它已经对参数和返回类型做了类似的事情。

或者,编译器将负责创建一个合成辅助方法来封装类型转换和方法调用,就像您编写了一个 lambda 表达式一样。这不是一个独特的情况。如果您使用对 varargs 方法的方法引用或数组创建,例如String[]::new,它们不能表示为直接方法句柄,最终会出现在合成辅助方法中。

无论哪种情况,我们都可以将当前行为视为错误。但显然,编译器和 JRE 开发人员必须就应该以何种方式处理它达成一致,然后我们才能说出错误存在于哪一边。

关于java - LambdaConversionException 与泛型 : JVM bug?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31711967/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com