轻松声明具有交集类型的Java Lambda表达式

3

假设我有一个如下所示的方法:

public <T extends Supplier<Collection<String>> & Serializable> void doSomething(T supplier){
    new ArrayList<String>().stream().collect(Collectors.toCollection(supplier));
}

为什么会这样呢?
doSomething(() -> new ArrayList<>());

导致了一个问题,但是...
doSomething((Supplier<Collection<String>> & Serializable)() -> new ArrayList<>());

这样可以吗?在这两种情况下,Lambda本身是完全一样的,在第二种情况下它可以工作。这意味着JVM能够创建可序列化的Lambda,但编译器不能识别这一点吗?

编辑:将第一个调用更改为我想要的。


3
() -> ArrayList::new 尝试通过方法引用实现一个 Collection 接口。你是不是想要使用 ArrayList::new 或者 () -> new ArrayList<>() 代替它? - Holger
哈哈,是的,我的错误,我将 ArrayList::new 更改为 () -> new ArrayList<>() 以更好地说明我的问题,但忘记将方法引用更改为调用。谢谢! - Domas Poliakas
1个回答

0

来自JLS 15.16. Cast Expressions:

强制类型转换可以用于显式地“标记”具有特定目标类型的lambda表达式或方法引用表达式。为了提供适当的灵活性,目标类型可以是表示交集类型的类型列表,前提是该交集引导一个函数接口(§9.8)。

并且没有解释为什么它不能自动推断。我的猜测是:这可能是可能的,但尚未实现。还有Eugene在评论中所说的有趣之处。这是否意味着类似的东西即将在Java 9中出现?


2
问题明显是关于通过lambda表达式或方法引用创建可序列化的Supplier。 OP希望从目标类型T extends Supplier <Collection <String>>&Serializable中推断出这一点... - Holger
3
我想 () -> ArrayList::new 只是个打字错误。实际问题上,使用 ArrayList::new 还是 () -> new ArrayList<>() 没有区别。我猜测发帖者尝试过这两种方式并在撰写问题时弄混了它们,但实际问题是当让编译器推断交集类型时,代码没有正常运行,需要进行类型转换才能解决。 - Holger
无法进一步阐述...也许我以后可以继续研究;-) - Roland
Holger所说的就是发生的事情 - 我最初写成了ArrayList::new,然后想要更改为() -> new ArrayList<>(),但搞砸了。 - Domas Poliakas
2
@Holger 这很有趣,Eclipse编译器(Java 9)可以编译没有强制转换的部分,而javac 8和9则失败了。 - Eugene
好的...已经删除了关于错误的部分...现在回答中剩下的不多了;-)也许可以帮助其他人深入挖掘... - Roland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接