I am in the process of learning Java 8 and I came across something that I find a bit strange.
Consider the following snippet:
private MyDaoClass myDao;
public void storeRelationships(Set<Relationship<ClassA, ClassB>> relationships) {
RelationshipTransformer transformer = new RelationshipTransformerImpl();
myDao.createRelationships(
relationships.stream()
.map((input) -> transformer.transformRelationship(input))
.collect(Collectors.toSet())
);
}
Basically, I need to map the input set called relationships
to a different type in order to
conform to the API of the DAO I'm using. For the conversion, I would like to use an existing RelationshipTransformerImpl
class that I instantiate as a local variable.
Now, here's my question:
If I was to modify the above code as follows:
public void storeRelationships(Set<Relationship<ClassA, ClassB>> relationships) {
RelationshipTransformer transformer = new RelationshipTransformerImpl();
myDao.createRelationships(
relationships.stream()
.map((input) -> transformer.transformRelationship(input))
.collect(Collectors.toSet())
);
transformer = null; //setting the value of an effectively final variable
}
I would obviously get a compilation error, since the local variable transformer
is no longer "effectively final". However, if replace the lambda with a method reference:
public void storeRelationships(Set<Relationship<ClassA, ClassB>> relationships) {
RelationshipTransformer transformer = new RelationshipTransformerImpl();
myDao.createRelationships(
relationships.stream()
.map(transformer::transformRelationship)
.collect(Collectors.toSet())
);
transformer = null; //setting the value of an effectively final variable
}
Then I no longer get a compilation error! Why does this happen? I thought the two ways to write the lambda expression should be equivalent, but there's clearly something more going on.