当前位置: 首页 > 知识库问答 >
问题:

为什么lambda强迫我使用单元素数组而不是final对象?

金晨
2023-03-14

我有以下课程:

public class Item{
   private String name;
   //setter getter
}

以及物品的收集。我想知道集合中最后一项的名称。为此,我只需遍历所有集合并使用last。问题是我不知道为什么它强迫我使用单元素字符串数组。

为什么我必须使用:

String[] lastName = {""};
items.forEach(item -> lastName[0] = item.getName());
System.out.println(lastname[0]);

而不是:

final String lastName;
items.forEach(item -> lastName = item.getName());
System.out.println(lastname);

共有2个答案

艾敏学
2023-03-14

最终实际上意味着您必须分配它一次(并且只有一次,由编译时分析保证)。例如,以下代码无效:

final String lastName;
List<Item> items = new ArrayList<Item>();
items.add(new Item("only one element"));
for (Item item:items) lastName = item.getName();

在第二个lambda表达式中,使用者将已声明为< code>final的< code>lastName赋值为:

final String lastName;
items.forEach(item -> lastName = item.getName());

由于lambda表达式中引用的变量必须是有效的最终变量(即可以将最终关键字添加到其定义中),因此删除lastName声明中的最终关键字没有帮助:此处lastName实际上是最终变量,并且消费者分配给一个有效的最终变量。

String lastName; 
items.forEach(item -> lastName = item.getName());

另一方面,在第一个表达式中,有效的最终变量是< code>lastName,这是一个数组。然后你可以做:

  String[] lastName = {""};
  items.forEach(item -> lastName[0] = item.getName());

因为在这里,您没有分配给有效的最终变量,而只是修改其元素(请记住,常量是引用,而不是其值),就像以下示例中的情况一样:

  final String[] lastName = new String[1];
  lastName[0]="foo";
杨晓博
2023-03-14

您不能将lastName设为String,因为在lambda(或匿名内部类)中使用的局部变量必须(有效地)Final(请参阅此处),即您不能在. foreach循环中lambda的每次执行中覆盖它。使用数组(或其他一些包装器对象)时,您不会为该变量分配新值,而只是更改它的某些方面,因此它可以是最终的。

或者,您可以使用< code>reduce跳到最后一项:

String lastName = items.stream().reduce((a, b) -> b).get().getName();

或者,如注释中所述,跳过前n-1个元素,然后取第一个元素:

String last = items.stream().skip(items.size() - 1).findFirst().get().getName();
 类似资料:
  • 我们有一个泽西1.18 jax-rs服务,它曾经使用jersey-json包来支持JSON。我们正在尝试迁移以使用MOXy,但不会破坏我们的JSON接口。不幸的是,jersey-json将单个元素列表编组为对象,将多元素列表编组为数组。默认情况下,MOXy将所有长度的列表编组为数组。我们知道MOXy编组的方式对客户端来说更容易使用,但是我们已经有很多客户端使用我们的接口,并且开始将单个元素列表编组

  • 问题内容: Java (可能还有许多其他类)内部发生的事情是有一个内部对象,对象被写入其中。每当从元素中读取元素时,都会进行转换。因此,每次读取时都要进行转换。 我不知道为什么要这样做。对我来说,似乎他们只是在做不必要的演员。只创建一个,然后不进行强制转换,是否更合乎逻辑,并且速度稍快一些?每次阵列创建仅一次强制转换,通常 远 少于读取次数。 为什么首选他们的方法?我看不出为什么我的想法并不严格吗

  • 问题内容: 为什么将类实现为常规类而不是将 抽象方法实现为 抽象 类。 会不会带来任何问题?或以这种方式有什么用吗? 而且,该方法应该是一种非常特定的方法, 其功能不能由任何其他类实现 (如果我没记错的话)。因此,我想该关键字比其他任何方法都更适合此操作。 但是我可以重写此方法并根据需要使用它, 它显然只印了, 有人告诉你我会产生一个新线程吗? 除了使工程师取代您感到困惑之外,还有什么其他用途?

  • 我碰巧知道,在下面的表达式中,使用将导致无限流,将始终为0。我之所以困惑是因为我认为返回的值没有被使用,即便如此,它也不应该中断之后的增量。

  • 问题内容: 我一直在阅读Go,并为这个基本问题感到困惑。 在Go中,很明显,切片更灵活,并且在需要一系列数据时通常可以代替数组使用。 阅读了大多数文档,他们似乎鼓励开发人员只使用切片而不是数组。我得到的印象是,创建者可以简单地将数组设计为可调整大小的,而无需整个切片部分即可完成。实际上,这样的设计会使该语言更易于理解,甚至鼓励使用更多惯用的代码。 那么,为什么创建者首先要允许数组呢?什么时候可以使

  • 问题内容: 为什么这样 代替这个 问题答案: 因为如果抛出异常,则 除非 捕获到异常, 否则 在执行 该块之后没有任何代码。一个块总是执行,不管你里面发生了什么块。 __