Accessing Members in an Enclosing Class – Functional-Style Programming

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):

Click here to view code image

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

Click here to view code image

p.test(“never dies!”) + ” ” + obj.banner

now evaluates as

Click here to view code image

true + ” ” + “love never dies!”

Example 13.1 Accessing Members in the Enclosing Object

Click here to view code image

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:

Click here to view code image

List: [Tom, Dick, Harriet]
true love never dies!

Leave a Comment