Method reference does not always seem to capture instance

It seems to me that in the first example the lambda captured the state of the Person object when it was created and does not try to re-evaluate it when it is called, when in the second case, it seems like it did not capture it, but revaluates it when it is called.

First of all, it's a method reference, not a lambda expression.

In both cases a reference to the Person instance is captured by the method reference (which is not "the state of the Person object"). That means that if the state of the Person instance is mutated, the result of executing the functional interface's method may change.

The method reference does not create a copy of the Person instance whose reference it captures.


This has nothing to do with lambdas or method references in a way, it's just side effects of these constructs that you are using.

For a much simpler reasoning you could think about it as:

static class SupplierHolder {
    private final Person p;
    // constructor/getter
}

static class Person {
    private String name;
    // constructor/getter/setter
}

When you create: Supplier<String> f = p::getName;, you can think about it as creating a SupplierHolder that takes a Person as input and has a method reference to its getName.

It's like doing:

Person p = new Person("Bob");
SupplierHolder sh = new SupplierHolder(p);
p = null; // this has no effect on the reference that SupplierHolder holds
System.out.println(sh.getPerson().getName()); 

In your second example, you have:

Person p = new Person("Bob");
SupplierHolder sh = new SupplierHolder(p); 
p.setName("Alice");

Now p reference and the reference that SupplierHolder holds, "act" on the same instance - they point to the same Object.

It's not exactly the same in reality, but proves the point, I guess.