【问题标题】:Java 8 stream variable used in lambda should be final or effectively final [duplicate]lambda中使用的Java 8流变量应该是最终的或有效的最终[重复]
【发布时间】:2019-01-17 15:18:15
【问题描述】:

这个问题已经被问过了。但是今天我发现了一些奇怪的东西。对于以下代码:-

public static List<EsbBucketInstanceDefinition> convertBucketDefinitionList(List<BucketInstanceDefinitionV1> bucketInstanceDefinitionV1List) {
    List<EsbBucketInstanceDefinition> response = new ArrayList<>();
    List<EsbBucketInstanceDefinition> finalResponse = new ArrayList<>();
    bucketInstanceDefinitionV1List.stream().forEach(e -> {
        EsbBucketInstanceDefinition esbBucketInstanceDefinition = new EsbBucketInstanceDefinition();
        esbBucketInstanceDefinition.setInstanceType(e.getInstanceType());
        esbBucketInstanceDefinition.setReportingGroup(e.getReportingGroup());
        esbBucketInstanceDefinition.setSliceVolume(e.getSliceVolume());
        esbBucketInstanceDefinition.setCounterName(e.getCounterName());
        esbBucketInstanceDefinition.setSubscriberGroupId(e.getSubscriberGroupId());
        // response.add(esbBucketInstanceDefinition); compiler error variable used in lambda should be final or effective final 
        finalResponse.add(esbBucketInstanceDefinition);
    });
    return finalResponse;
}

因为这很好用。看起来只有变量名 finalResponse 有效。如何以及为什么?这样做有效吗?

【问题讨论】:

  • 您不是在修改引用本身,而是添加到 ArrayList - 这会起作用,但不鼓励......
  • 还请注意,在您的情况下,您根本不需要streamList::forEach 存在
  • 你能问一下为什么不鼓励吗?请解释更多。推荐的方式是什么?
  • 推荐使用map(....).collect(Collectors.toList())的方法。在文档中搜索副作用
  • 您可以改进您的代码,在EsbBucketInstanceDefinition 中创建一个构造函数,并在collect 的流中使用mappublic static List&lt;EsbBucketInstanceDefinition&gt; convertBucketDefinitionList(List&lt;BucketInstanceDefinitionV1&gt; bucketInstanceDefinitionV1List) { return bucketInstanceDefinitionV1List.stream() .map(e -&gt; new EsbBucketInstanceDefinition(e.getInstanceType(), e.getReportingGroup(), e.getSliceVolume(), e.getCounterName(), e.getSubscriberGroupId())) .collect(Collectors.toList()); }

标签: java variables java-8 java-stream final


【解决方案1】:

只能(有效地)从 lambda 中引用最终变量。

finalResponse 持有的引用实际上是最终的,因为它永远不会改变。请注意,更改引用意味着为其分配一个新值,例如

finalResponse = someOtherList;

更改所引用对象的状态(例如,将项目添加到finalResponse 所引用的列表中)与变量finalResponse 所持有的值无关,即

finalResponse.add(something);

不改变变量finalResponse;它只会更改finalResponse 所指的对象。

【讨论】:

  • 如果这是要推断的问题,那么关闭this as a duplicate怎么样?由于这仍然与问题中注释掉的代码无关。至少,使用mapcollect 的建议可以通过完全不使用 lambda 来解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多