2013-06-04 3 views
2

У меня есть вложенный статический класс с именем Adjudicator (не спрашивайте ... Я назвал его немного причудливым, прежде чем я прочитал о шаблоне Builder в Effective Java), который является строителем, то есть Client.Adjudicator создает клиентские объекты.Почему возможно получить доступ к элементам вложенного статического класса?

Как строитель, который Джошуа Блох дает в качестве примера в Эффективной Java, он строит объекты класса «вложения» (статические вложенные классы не являются действительно закрытыми) путем вызова конструктора охватывающего класса. Мой класс выглядит следующим образом:

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); 
     } 
    } 
} 

статический вложенный класс, с точки зрения виртуальной машины Java, класс верхнего уровня и поэтому экземпляры этого не зависят от любого экземпляра Клиента.

И все же мой класс Client может свободно обращаться к закрытым членам своего класса-строителя ... хотя они являются частными и находятся в отдельном классе верхнего уровня.

Почему это работает? Разве это не разрушает инкапсуляцию? Я рад, что это работает, но это не интуитивно для меня.

+0

Неважно. Я вижу ответ сейчас, как только я разместил вопрос. Это не тот класс, к которому он обращается к вложенному классу; это неправильный способ взглянуть на это. Конструктор в Client передается экземпляр строителя. Уровень доступа строителя является общедоступным ... даже несмотря на это, члены явно объявляются с закрытым доступом. Итак, почему конструктор может получить доступ к ним через пройденную ссылку? – scottb

+0

Это своего рода методы и переменные уровня пакета. Классы в одном пакете могут обращаться друг к другу. Классы вне этого пакета не могут. В этом случае 'private', область действия - это не пакет, а единица компиляции (или называть его« файлом »или« внешним классом »). –

+0

@Nealon, вложенный статический класс, как класс верхнего уровня. Точно так же, как один. Вы можете создавать экземпляры вложенного статического класса так же, как и любой другой класс верхнего уровня, и передавать ссылки этих экземпляров. Вы не можете думать о статических классах точно так же, как вы думаете о статических полях. – scottb

ответ

3

статический вложенный класс, с точки зрения виртуальной машины Java, класс верхнего уровня

Не так, как вы выяснили. Объем частного участника - это класс включения верхнего уровня. В вашем случае это целый класс Client.

Обратите внимание, что он работает в обоих направлениях, и ваш класс Adjudicator может получить доступ к закрытым членам вашего класса Client.

Ссылка: JLS #6.6.1

если член объявлена ​​частной, то доступ разрешен, если и только если оно происходит в теле класса верхнего уровня, покрывающего заявление члена

+0

«Обратите внимание, что он работает в обоих направлениях, и ваш класс Adjudicator также может получить доступ к закрытым членам вашего класса Client». Это не может быть правдой, не так ли? Экземпляры класса Client.Adjudicator могут существовать, даже если экземпляров клиента вообще нет. – scottb

+0

Если вы создадите экземпляр клиента в судизаторе или получите доступ к нему, вы сможете получить доступ к его частным членам экземпляра. И без экземпляра вы можете получить доступ к своим частным статическим членам. – assylias

+0

Кажется, существует различие между областью видимости и уровнем доступа, о котором я раньше не думал. Вложенные классы-члены рассматриваются JVM в той же области, что и внешний класс, даже если члены-уровни доступа в противном случае сделали бы эти члены недоступными.Я заметил с некоторым интересом, что JVM делает что-то за кулисами, чтобы сделать этот доступ возможным ... конструктор клиента получает доступ к полям Adjudicator через некоторое средство, называемое WriteObject() .... – scottb

Смежные вопросы