Accessing Members in an Enclosing Class
Just like nested blocks, a lambda expression has lexical or block scope—that is, names used in a lambda expression are resolved lexically in the local context in which the lambda expression is defined.
A lambda expression does not inherit names of members declared in the functional interface it implements, which obviously then cannot be accessed in the lambda body.
Since a lambda expression is not a class, there is no notion of the this reference. If the this reference is used in a lambda expression in a non-static context, it refers to the enclosing object, and can be used to access members of this object. The name of a member in the enclosing object has the same meaning when used in a lambda expression. In other words, there are no restrictions to accessing members declared in the enclosing object. In the case of shadowing member names by local variables, the keyword this can be explicitly used, and also the keyword super to access any members inherited by the enclosing object.
In Example 13.1, the getPredicate() method at (7) defines a lambda expression at (8). This lambda expression is defined in a non-static context (i.e., an instance method). This lambda expression accesses the static field strList and the instance field banner in the enclosing class at (1) and (2), respectively.
In the main() method in Example 13.1, an ArrayList<String> is assigned to the static field strList at (3) and is initialized. The ArrayList<String> referred to by the static field strList has the following content:
[Tom, Dick, Harriet]
A MembersOnly object is created at (4). Its StringBuilder field banner is initialized with the string “love “. The local variable obj declared at (4) refers to this MembersOnly object. At (5), a Predicate<String> instance is instantiated by calling the getPredicate() method on the MembersOnly object referred to by the local variable obj. This predicate is first executed when the test() method is called at (6) on the Predicate<String> instance, with the argument string “never dies!”. Calling the test() method results in the lambda expression created at (5) by the getPredicate() method to be executed in the context of the enclosing MembersOnly object referred to by the local variable obj.
The parameter str of the lambda expression is initialized with the string “never dies!”—that is, the argument to the test() method. In the body of the lambda expression, the ArrayList<String> referred to by the static field strList in the MembersOnly class is first printed at (9):
List: [Tom, Dick, Harriet]
At (10), the parameter str (with contents “never dies!”) is appended to the StringBuilder (with contents “love “) referred to by the instance field banner in the enclosing object, resulting in the following contents in this StringBuilder:
“love never dies!”
Since the length of the string “never dies!”, referred to by the parameter str, is greater than 5, the lambda expression returns true at (11). This is the value returned by the test() method call at (6).
In the call to the println() method at (6), the argument
p.test(“never dies!”) + ” ” + obj.banner
now evaluates as
true + ” ” + “love never dies!”
Example 13.1 Accessing Members in the Enclosing Object
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class MembersOnly {
// Instance variable
private StringBuilder banner; // (1)
// Static variable
private static List<String> strList; // (2)
// Constructor
public MembersOnly(String str) {
banner = new StringBuilder(str);
}
// Static method
public static void main(String[] args) {
strList = new ArrayList<>(); // (3)
strList.add(“Tom”); strList.add(“Dick”); strList.add(“Harriet”);
MembersOnly obj = new MembersOnly(“love “); // (4)
Predicate<String> p = obj.getPredicate(); // (5)
System.out.println(p.test(“never dies!”) + ” ” + obj.banner); // (6)
}
// Instance method
public Predicate<String> getPredicate() { // (7)
return str -> { // (8) Lambda expression
System.out.println(“List: ” + MembersOnly.strList);// (9) Static field
this.banner.append(str); // (10) Instance field
return str.length() > 5; // (11) boolean value
};
}
}
Output from the program:
List: [Tom, Dick, Harriet]
true love never dies!