Accessing Members in Enclosing Context – Nested Type Declarations 04/22/2023 Rivka Scheinberg Post in Determining the Range,Oracle Exams,Static Member Types Accessing Members in Enclosing Context An implicit reference to the enclosing object is always available in every method and constructor of a non-static member class. A method or constructor can explicitly specify this reference using a special form of the this construct and access its enclosing object, as explained in the next example. From within a non-static member class, it is possible to refer to all members in the enclosing class directly, unless they are hidden. An example is shown at (9) in Example 9.5, where the instance field message in an object of the enclosing class is accessed by its simple name in the non-static member class. It is also possible to explicitly refer to members in the enclosing class, but this requires special usage of the this reference. One might be tempted to write the statement at (9) as follows: Click here to view code image return this.message + ” in ” + this.nodeInfo + ” (” + this.maxNumOfNodes + “)”; // (9a) Not ok. The reference this.nodeInfo is correct because the field nodeInfo certainly belongs to the current object (denoted by this) of the Node class, but this.message cannot possibly work, as the current object (indicated by this) of the Node class has no field named message. The correct syntax is the following: Click here to view code image return MyLinkedList.this.message + ” in ” + this.nodeInfo + ” (” + this.maxNumOfNodes + “)”; // (9b) The expression (called the qualified this) enclosing_class_name.this evaluates to a reference that denotes the enclosing object (of the specified class) that is associated with the current instance of a non-static member class. Accessing Hidden Members Fields and methods in the enclosing context can be hidden by fields and methods with the same names in the non-static member class. The qualified this can be used to access members in the enclosing context, somewhat analogous to using the keyword super in subclasses to access hidden superclass members. Example 9.6 Qualified this and Qualified Class Instance Creation Expression Click here to view code image // File: OuterInstances.javaclass TLClass { // (1) TLC private String id = “TLClass “; // (2) public TLClass(String objId) { id = id + objId; } // (3) public void printId() { // (4) System.out.println(id); } class InnerB { // (5) NSMC private String id = “InnerB “; // (6) public InnerB(String objId) { id = id + objId; } // (7) public void printId() { // (8) System.out.print(TLClass.this.id + ” : “); // (9) Refers to (2) System.out.println(id); // (10) Refers to (6) } class InnerC { // (11) NSMC private String id = “InnerC “; // (12) public InnerC(String objId) { id = id + objId; } // (13) public void printId() { // (14) System.out.print(TLClass.this.id + ” : “); // (15) Refers to (2) System.out.print(InnerB.this.id + ” : “); // (16) Refers to (6) System.out.println(id); // (17) Refers to (12) } public void printIndividualIds() { // (18) TLClass.this.printId(); // (19) Calls (4) InnerB.this.printId(); // (20) Calls (8) printId(); // (21) Calls (14) } } // InnerC } // InnerB} // TLClass//_____________________________________________________________________________public class OuterInstances { // (22) public static void main(String[] args) { // (23) TLClass a = new TLClass(“a”); // (24) TLClass.InnerB b = a.new InnerB(“b”); // (25) b –> a TLClass.InnerB.InnerC c1 = b.new InnerC(“c1”); // (26) c1 –> b TLClass.InnerB.InnerC c2 = b.new InnerC(“c2”); // (27) c2 –> b b.printId(); // (28) c1.printId(); // (29) c2.printId(); // (30) System.out.println(“————“);TLClass.InnerB bb = new TLClass(“aa”).new InnerB(“bb”); // (31) TLClass.InnerB.InnerC cc = bb.new InnerC(“cc”); // (32) bb.printId(); // (33) cc.printId(); // (34) System.out.println(“————“); TLClass.InnerB.InnerC ccc = new TLClass(“aaa”).new InnerB(“bbb”).new InnerC(“ccc”);// (35) ccc.printId(); // (36) System.out.println(“————“); ccc.printIndividualIds(); // (37) }} Output from the program: Click here to view code image TLClass a : InnerB bTLClass a : InnerB b : InnerC c1TLClass a : InnerB b : InnerC c2————TLClass aa : InnerB bbTLClass aa : InnerB bb : InnerC cc————TLClass aaa : InnerB bbb : InnerC ccc————TLClass aaaTLClass aaa : InnerB bbbTLClass aaa : InnerB bbb : InnerC ccc Example 9.6 illustrates the qualified this employed to access members in the enclosing context, and also demonstrates the qualified class instance creation expression employed to create instances of non-static member classes. The example shows the non-static member class InnerC at (11), which is nested in the non-static member class InnerB at (5), which in turn is nested in the top-level class TLClass at (1). All three classes have a private non-static String field named id and a non-static method named printId. The member name in the nested class hides the name in the enclosing context. These members are not overridden in the nested classes because no inheritance is involved. In order to refer to the hidden members, the nested class can use the qualified this, as shown at (9), (15), (16), (19), and (20). Within the nested class InnerC, the three forms used in the following statements to access its field id are equivalent: Click here to view code image System.out.println(id); // (17)System.out.println(this.id); // (17a)System.out.println(InnerC.this.id); // (17b) The main() method at (23) uses the special syntax of the new operator to create objects of non-static member classes and associate them with enclosing objects. An instance of class InnerC (denoted by c1) is created at (26) in the context of an instance of class InnerB (denoted by b), which was created at (25) in the context of an instance of class TLClass (denoted by a), which in turn was created at (24). Click here to view code image TLClass a = new TLClass(“a”); // (24)TLClass.InnerB b = a.new InnerB(“b”); // (25) b –> aTLClass.InnerB.InnerC c1 = b.new InnerC(“c1”); // (26) c1 –> b The reference c1 is used at (29) to invoke the method printId() declared at (14) in the nested class InnerC. This method prints the field id from all the objects associated with an instance of the nested class InnerC. Click here to view code image TLClass a : InnerB b : InnerC c1 When the intervening references to an instance of a non-static member class are of no interest—that is, if the reference values need not be stored in variables—the new operator can be chained as shown at (31) and (35). Click here to view code image TLClass.InnerB bb = new TLClass(“aa”).new InnerB(“bb”); // (31)…TLClass.InnerB.InnerC ccc = new TLClass(“aaa”).new InnerB(“bbb”).new InnerC(“ccc”);// (35) Note that the (outer) objects associated with the instances denoted by the references c1, cc, and ccc (at (26), (32), and 35), respectively) are distinct, as evident from the program output. However, the instances denoted by references c1 and c2 (at (26) and (27), respectively) have the same outer objects associated with them.