THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

object is created, as shown in the deposit and withdraw methods. When an inner class object is created,
it must be associated with an object of its enclosing class. Usually, inner class objects are created inside
instance methods of the enclosing class, as in deposit and withdraw. When that occurs the current object
this is associated with the inner object by default. The creation code in deposit is the same as the more
explicit


lastAct = this.new Action("deposit", amount);


Any BankAccount object could be substituted for this. For example, suppose we add a transfer operation
that takes a specified amount from one account and places it in the current accountsuch an action needs to
update the lastAct field of both account objects:


public void transfer(BankAccount other, long amount) {
other.withdraw(amount);
deposit(amount);
lastAct = this.new Action("transfer", amount);
other.lastAct = other.new Action("transfer", amount);
}


In this case we bind the second Action object to the otherBankAccount object and store it as the last
action of the other account. Each BankAccount object should only refer to Action objects for which that
BankAccount object is the enclosing instance. It would make no sense above, for example, to store the
same Action object in both the current lastAct field and other.lastAct.


An inner class declaration is just like a top-level class declaration except for one restrictioninner classes
cannot have static members (including static nested types), except for final static fields that are initialized to
constants or expressions built up from constants. The rationale for allowing constants to be declared in an
inner class is the same as that for allowing them in interfacesit can be convenient to define constants within
the type that uses them.


As with top-level classes, inner classes can extend any other classincluding its enclosing class[2] implement
any interface and be extended by any other class. An inner class can be declared final or abstract, and
can have annotations applied to it.


[2] It is hard to think of a reason why you would want to do this, and easy to get a headache
reasoning about what it means.

Exercise 5.2: Create a version of BankAccount that records the last ten actions on the account. Add a
history method that returns a History object that will return Action objects one at a time via a next
method, returning null at the end of the list. Should History be a nested class? If so, should it be static or
not?


5.2.1. Accessing Enclosing Objects


The toString method of Action directly uses the number field of its enclosing BankAccount object.
A nested class can access all members of its enclosing classincluding private fields and methodswithout
qualification because it is part of the enclosing class's implementation. An inner class can simply name the
members of its enclosing object to use them. The names in the enclosing class are all said to be in scope. The
enclosing class can also access the private members of the inner class, but only by an explicit reference to an
inner class object such as lastAct. While an object of the inner class is always associated with an object of
the enclosing class, the converse is not true. An object of the enclosing class need not have any inner class

Free download pdf