Java 8 stream variable used in lambda should be final or effectively final

Viewed 15934

This question is already asked. But today I found something odd. For the following code:-

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;
}

For this works fine. Looks like only variable name finalResponse is working. How and why? Is it valid to do?

1 Answers

References may only be made to (effectively) final variables from within a lambda.

The reference held by finalResponse in effectively final, because it never changes. Note that changing the reference means assigning a new value to it, eg

finalResponse = someOtherList;

Changing the state of the object referred to (eg adding items to the list referred to by finalResponse) is irrelevant to what the value held by the variable finalResponse, ie

finalResponse.add(something);

Does not change the variable finalResponse; it only changes the object to which finalResponse refers.

Related