2013-06-04 2 views
2

작성자 인 Adjudicator라는 중첩 된 정적 클래스 (요청하지 않음 ... 실용적인 Java의 작성자 패턴에 대해 읽었을 때)를 작성했습니다. 즉 Client.Adjudicator가 클라이언트 객체를 작성합니다.왜 중첩 된 정적 클래스의 멤버에 액세스 할 수 있습니까?

Joshua Bloch가 Effective 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); 
     } 
    } 
} 

정적 중첩 클래스는 JVM, 최상위 클래스의보기 때문에 그것의 인스턴스가 클라이언트의 인스턴스에 의존하지 않는 점에서이다.

그러나 클라이언트 클래스는 개인 클래스이고 별도의 최상위 클래스이지만 자유롭게 빌더 클래스의 private 멤버에 액세스 할 수 있습니다.

왜이 기능이 작동합니까? 이것은 캡슐화를 깨뜨리지 않습니까? 나는 이것이 효과가있어 행복하다. 그러나 이것은 나에게 직관적이지 않다. 당신이 발견 한 것처럼

+0

신경 쓰지 마. 나는 질문을 게시하자마자 대답을 지금 본다. 중첩 클래스에 액세스하는 클래스가 아닙니다. 그것은 이것을 보는 잘못된 길입니다. Client의 생성자에는 빌더의 인스턴스가 전달됩니다. 빌더의 액세스 레벨은 public입니다 ... 그렇더라도 구성원은 명시 적으로 개인 액세스로 선언됩니다. 그렇다면 생성자는 전달 된 참조를 통해 왜 액세스 할 수 있습니까? – scottb

+0

패키지 수준의 메소드 및 변수와 비슷합니다. 동일한 패키지의 클래스는 서로의 클래스에 액세스 할 수 있습니다. 해당 패키지 외부의 클래스는 할 수 없습니다. 이 경우'private'는 패키지가 아니라 컴파일 유닛 (또는 '파일'또는 '외부 클래스'라고 함)입니다. –

+0

@Nealon, 중첩 된 정적 클래스는 최상위 클래스와 같습니다. 하나처럼. 다른 최상위 클래스와 마찬가지로 중첩 된 정적 클래스의 인스턴스를 만들고 해당 인스턴스의 참조를 전달할 수 있습니다. 정적 클래스는 정적 필드를 생각하는 것과 똑같은 방식으로 생각할 수 없습니다. – scottb

답변

3

정적 중첩 클래스는 아니 정확히 JVM, 최상위 클래스의 관점에서,

입니다. 개인 멤버의 범위는 최상위 수준의 둘러싸는 클래스입니다. 귀하의 경우, 전체 Client 클래스입니다.

두 가지 방법으로 작동하며 Adjudicator 클래스는 Client 클래스의 개인 멤버에도 액세스 할 수 있습니다.

참조

: 회원이 개인 선언 된 경우 JLS #6.6.1

, 다음 액세스 및 경우 허용 된 경우에만이 멤버의 선언을 둘러싸는 최상위 클래스의 신체 내에서 발생하는 경우

+0

"두 가지 방법으로 모두 작동하며 Adjudicator 클래스가 Client 클래스의 비공개 멤버에도 액세스 할 수 있습니다." 이것은 사실 일 수 없습니다. Client 인스턴스가 전혀없는 경우에도 Client.Adjudicator 클래스의 인스턴스가 존재할 수 있습니다. – scottb

+0

Adjudicator에서 Client의 인스턴스를 생성하거나 액세스하면 개인 인스턴스 멤버에 액세스 할 수 있습니다. 인스턴스가 없으면 개인 정적 멤버에 액세스 할 수 있습니다. – assylias

+0

이전에는 생각하지 못했던 범위와 액세스 수준 사이에는 차이점이있는 것으로 보입니다. 중첩 된 멤버 클래스는 멤버 액세스 수준이 그렇지 않으면 구성원을 액세스 할 수 없게 만들지라도 JVM에 의해 외부 클래스와 동일한 범위에있는 것으로 간주됩니다.나는 JVM이이 접근을 가능하게하기 위해 무대 뒤에서 뭔가를하고 있다는 것에 관심을 표명했다. 클라이언트 생성자는 WriteObject()라는 일부 기능을 통해 Adjudicator 필드에 대한 액세스를 얻는다. – scottb

관련 문제