java - 在 Java 中,为什么我不能使用 lambda 作为增强的 for 循环表达式?

标签 java foreach lambda java-8

假设我们有一个 Iterator<Integer> iterator .因为Iterable是一个函数式接口(interface),我们可以这样写:

Iterable<Integer> iterable = () -> iterator;

我们当然可以使用 iterable作为for循环的增强表达式:

for (Integer i : iterable) foo(i);

那是为什么

for (Integer i : () -> iterator) foo(i);

不允许? (它会导致以下编译器错误:)

error: lambda expression not expected here
    for (Integer i : () -> iterator) foo(i);
                     ^

明确目标类型

for (Integer i : (Iterable<Integer>) () -> iterator) foo(i);

显然有效,但是如果省略 λ 表达式,为什么编译器不能推断出它的目标类型?从 Expression 是 λ 表示法这一事实来看,编译器是否不清楚目标类型不能是 Array ,因此必须是 Iterable ?

这只是语言设计者的疏忽,还是我在这里遗漏了什么?

最佳答案

这不仅仅是关于 lambda 表达式;它是关于所有需要目标类型的多边形表达式。

可以肯定的是,这不是疏忽。该案被考虑并驳回。

引用早期规范:

http://cr.openjdk.java.net/~dlsmith/jsr335-0.9.3/D.html

Deciding what contexts are allowed to support poly expressions is driven in large part by the practical need for such features:

The expression in an enhanced for loop is not in a poly context because, as the construct is currently defined, it is as if the expression were a receiver: exp.iterator() (or, in the array case, exp[i]). It is plausible that an Iterator could be wrapped as an Iterable in a for loop via a lambda expression (for (String s : () -> stringIterator)), but this doesn't mesh very well with the semantics of Iterable.

我的看法是,每次调用 Iterable.iterator()必须返回一个新的、独立的迭代器,位于开头。然而,示例(以及您的示例)中的 lambda 表达式返回 same 迭代器。这不符合 Iterable 的语义。 .


无论如何,在 for-each 循环中支持目标输入似乎是不必要的工作。如果你已经有了迭代器,你可以简单地做

    iterator.forEachRemaining( element->{ ... } )

或者如果你更喜欢老派

    while(iterator.hasNext()) {
        Foo elment = iterator.next();

两者都不好;使语言规范更加复杂是不值得的。 (如果我们确实希望 for-each 提供目标类型,请记住它也需要适用于其他 poly 表达式,例如 ?: ;那么在某些情况下 for-each 可能变得难以理解。一般来说,有两种可能的目标类型,Iterable<? extends X> | X[],这对于类型推断系统来说是非常困难的。)


for-each 构造可以被视为语法糖,因为 lambda 不可用。如果语言已经有 lambda 表达式,那么真的没有必要有一个特殊的语言结构来支持 for-each;它可以通过库 API 来完成。

关于java - 在 Java 中,为什么我不能使用 lambda 作为增强的 for 循环表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32506732/

相关文章:

C++::Template 函数 - 从 object.function 获取对象的地址

c# - 如何将正确的字段放入组中并使用 linq 求和?

java - “找不到或加载主类”是什么意思?

C#:在类实例化上创建一个什么都不做的 Action

java - 如何使用 Hibernate 在 Spring Boot 中处理数据库迁移?

javascript - 当我尝试插入两条记录时,CUR_STOCK 表中只有一条记录得到更新?

php - DOM loadhtml提取节点和子节点

database - 如何在 Dart (Flutter) 中获取每个可迭代值的索引号

java - 调整 Controller 中的方法。 [持久性单元: default] Unable to build Hibernate SessionFactory

java - Android:使用 TabHost 和 TabWidget 自定义选项卡的外观