我有一些带有方法引用的代码,它编译得很好,但在运行时失败。
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());
}
}
当我将方法引用重写为一个琐碎的lambda时,一切都很好。在我看来,一个结构如预期的那样工作,而它的语义等价物却爆炸了,这似乎真的很可疑。
这可能在规范中吗?我正在非常努力地寻找一种方法,使它不成为编译器或运行时的问题,但还没有提出任何问题。
下面是一个简化的html" target="_blank">示例,它再现了这个问题,并且只使用核心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
传递到工厂。
或者,编译器将负责创建一个封装类型转换和方法调用的合成帮助器方法,就像您编写了一个lambda表达式一样。这不是一个独特的情况。如果将方法引用用于varargs方法或数组创建,例如string[]::new
,则不能将它们表示为直接方法句柄,而最终使用合成助手方法。
无论哪种情况,我们都可以将当前行为视为bug。但显然,编译器和JRE开发人员必须在确定bug位于哪一边之前,就应该以哪种方式处理它达成一致。
问题内容: 我有一个代表文本片段的泛型类。该文本片段可能具有多种不同模式(突出显示的不同类型)中的任何一种。这些模式用枚举表示。每个项目的Enum可能不同,但是它必须实现一个接口,该接口提供了一种将其中两个结合的方法(可以突出显示并加粗显示)。所以我有一个界面: 然后我的TextFragment是文本字符串和模式的容器。但是当我尝试声明该类时: 我收到以下错误: 令牌“扩展”的语法错误,预期 根据
如何获取这个类的类型?对于上下文,我使用ModelMapper,我需要类类型T从S转换为T。 背景: 我已经尝试了N种方法,其中我放置了“//一些方法来获取类型”,但没有任何效果。例如: 或
问题内容: 为什么这样做: 虽然这会产生类型不匹配错误: 为什么是这样?是否有办法解决此问题,而不使用原始类型? 问题答案: 尝试 注意:请注意,当您使用类似List的集合时,您只能在“只读”模式下使用它(添加空值除外)。
嗨,我正在努力让这两种方法发挥作用,但即使我尝试了几乎所有我能想到的方法,它仍然不起作用。请告诉我怎么修! 空添加(任何值):将一个包含newValue的节点添加到列表的末尾。 空添加(int index,任何值):在索引的节点之后添加一个包含newValue的节点(假设索引从0开始)。 下面是我的代码:(上面的方法显示在底部)
Java中是否有一种方法可以通过一个方法的声明返回不同的类型? 我希望此方法返回一个对象,并在函数调用时将其转换为正确的类型。这就是我的想法,但它不是这样工作的。我是否需要某种通用返回类型来执行此操作?解决这个问题的最佳方法是什么?
我在typescript中有以下泛型类 但是我不知道为什么得到这个错误Class'(匿名类)'不正确地扩展基类'列'。属性getValue的类型不兼容。类型'(值:数字)=