Consider following class:
class Foo<T> {
void handle(T t) {
System.out.println("handling " + t);
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
Foo<Integer> f = new Foo<>();
list.forEach(f::handle); // compiles fine
//list.forEach(obj -> f.handle(obj));// compilation error
f = new Foo<>(); // reassign f
}
}
Why do I get compilation error for obj -> f.handle(obj)
, but not for f::handle
?
Those are two different constructs that are doing two different things. In the first case, you are getting the method reference of a specific object: this needs to be done only once, after which the JVM has its own reference (so effectively final) to the object
f
and can call thehandle
method. In the second case, at each call the JVM has to resolve thef
reference and it thus complains thatf
must befinal
. You could easily write code that setsf
tonull
while theforEach
is running and thus cause a NPE.