I have a nested static class named Adjudicator (don't ask ... I had named it a bit whimsically before I had read about the Builder Pattern in Effective Java) which is a builder, i.e. Client.Adjudicator builds Client objects.
Like the builder that Joshua Bloch gives as an example in Effective Java, it builds objects of the "enclosing" class (static nested classes are not truly enclosed) by invoking the enclosing class's constructor. My class looks like this:
public class Client extends DB {
private IntegerProperty id = new SimpleIntegerProperty();
private LongProperty defmrnKey = new SimpleLongProperty();
private StringProperty lastName = new SimpleStringProperty();
private StringProperty midName = new SimpleStringProperty();
private StringProperty firstName = new SimpleStringProperty();
private IntegerProperty doB = new SimpleIntegerProperty();
private StringProperty gender = new SimpleStringProperty();
:
:
Client(Client cli) { // Copy constructor
this.id.set(cli.getID());
this.defmrnKey.set(cli.getDefMRNKey());
this.lastName.set(cli.getLastName());
this.midName.set(cli.getMidName());
this.firstName.set(cli.getFirstName());
this.doB.set(cli.getDoB());
this.gender.set(cli.getGender());
}
Client(Client.Adjudicator ad) { // Invoked by builder
this.id.set(ad.m_id);
this.defmrnKey.set(ad.m_defmrnkey);
this.lastName.set(ad.m_ln);
this.midName.set(ad.m_mn);
this.firstName.set(ad.m_fn);
this.doB.set(ad.m_dob);
this.gender.set(ad.m_gen);
}
:
:
public static class Adjudicator {
private int m_id = DB.KEY_UNDEFINED;
private long m_defmrnkey = DB.KEY_UNDEFINED;
private String m_ln = null;
private String m_mn = null;
private String m_fn = null;
private int m_dob = DB.KEY_UNDEFINED;
private String m_gen = null;
:
:
public Client build() {
// Invariants all checked here; if ok then...
return new Client(this);
}
}
}
The static nested class is, from the point of view of the JVM, a top-level class and so instances of it don't depend on any instance of Client.
And yet, my Client class is able to freely access the private members of its builder class ... even though they're private and in a separate top-level class.
Why does this work? Doesn't this break encapsulation? I'm happy that this works, but this is not intuitive to me.
The static nested class is, from the point of view of the JVM, a top-level class
Not exactly as you've found out. The scope of a private member is the top-level enclosing class. In your case, it is the whole Client
class.
Note that it works both ways and your Adjudicator
class can access the private members of your Client
class too.
Reference: JLS #6.6.1
if the member is declared private, then access is permitted if and only if it occurs within the body of the top level class that encloses the declaration of the member