외부 Java 클래스가 내부 클래스 개인 회원에게 액세스 할 수있는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1801718

문제

외부 클래스가 내부 클래스 개인 인스턴스 변수에 액세스 할 수 있음을 관찰했습니다. 이것이 어떻게 가능한지? 다음은 동일한 것을 보여주는 샘플 코드입니다.

class ABC{
    class XYZ{
        private int x=10;
    }

    public static void main(String... args){
        ABC.XYZ xx = new ABC().new XYZ();
        System.out.println("Hello :: "+xx.x); ///Why is this allowed??
    }
}

이 행동이 허용되는 이유는 무엇입니까?

도움이 되었습니까?

해결책

내부 클래스는 원래 외부 클래스에 속하는 일부 기능을 깨끗하게 분리하는 방법 일뿐입니다. 두 가지 요구 사항이있을 때 사용하도록 의도됩니다.

  1. 외부 클래스의 일부 기능이 별도의 클래스에서 구현 된 경우 가장 분명합니다.
  2. 별도의 클래스이지만 기능은 외부 클래스가 작동하는 방식과 매우 밀접한 관련이 있습니다.

이러한 요구 사항이 주어지면 내부 클래스는 외부 클래스에 완전히 액세스 할 수 있습니다. 그것들은 기본적으로 외부 클래스의 구성원이기 때문에 개인을 포함하여 외부 클래스의 방법과 속성에 액세스 할 수 있다는 것이 합리적입니다.

다른 팁

내면의 개인 구성원을 숨기고 싶다면 공개 회원과의 인터페이스를 정의 하고이 인터페이스를 구현하는 익명의 내부 클래스를 만들 수 있습니다. 예제 벨로그 :

class ABC{
    private interface MyInterface{
         void printInt();
    }

    private static MyInterface mMember = new MyInterface(){
        private int x=10;

        public void printInt(){
            System.out.println(String.valueOf(x));
        }
    };

    public static void main(String... args){
        System.out.println("Hello :: "+mMember.x); ///not allowed
        mMember.printInt(); // allowed
    }
}

내부 클래스는 (액세스 제어의 목적 상) 포함 클래스의 일부로 간주됩니다. 이는 모든 개인에게 완전히 접근 할 수 있음을 의미합니다.

이것이 구현되는 방식은 합성 패키지로 보호 된 방법을 사용하는 것입니다. 내부 클래스는 동일한 패키지 (ABC $ XYZ)의 별도 클래스로 컴파일됩니다. JVM은 이러한 수준의 분리를 직접 지원하지 않으므로 바이트 코드 레벨 ABC $ XYZ에서 외부 클래스가 개인 메소드/필드로 이동하는 데 사용하는 패키지 보호 메소드를 갖도록합니다.

이와 유사한 다른 질문에 정답이 나타납니다.동봉 된 클래스의 방법에 의해 중첩 클래스의 개인 구성원에게 액세스 할 수있는 이유는 무엇입니까?

그것은 개인 범위에 대한 정의가 있다고 말합니다. JLS- 접근성 결정:

그렇지 않으면, 멤버 또는 생성자가 개인으로 선언 된 경우 그런 다음 멤버 또는 생성자의 선언을 동봉하는 최상위 클래스 (§7.6)의 본문 내에서 발생하는 경우에만 액세스가 허용됩니다.

내부 클래스의 IMHO 중요한 사용 사례는 공장 패턴입니다. Enclosing 클래스는 액세스 제한이없는 내부 클래스의 인스턴스를 준비하고 인스턴스를 외부 세계로 전달할 수 있습니다.

모순으로 아 빅스 클래스 정적을 선언한다고해서 아래와 같이 액세스 제한을 둘러싸는 클래스로 변경하지는 않습니다. 또한 동일한 동봉 클래스에서 정적 클래스 간의 액세스 제한이 작동합니다. 놀랐습니다 ...

class MyPrivates {
    static class Inner1 { private int test1 = 2; }
    static class Inner2 { private int test2 = new Inner1().test1; }

    public static void main(String[] args) {
        System.out.println("Inner : "+new Inner2().test2);
    }
}

액세스 제한은 클래스별로 수행됩니다. 클래스에서 선언 된 메소드가 모든 인스턴스/클래스 멤버에 액세스 할 수없는 방법은 없습니다. 이것은 내부 클래스가 외부 클래스의 구성원들에게도 접근 할 수 없으며, 외부 클래스는 내부 클래스의 구성원에게 접근 할 수 없을 것입니다.

다른 클래스 내부에 클래스를 배치함으로써 구현에 단단히 연결되며 구현의 일부인 모든 것이 다른 부분에 액세스해야합니다.

내부 클래스의 논리는 외부 클래스에서 내부 클래스를 만들면 몇 가지를 공유해야하기 때문에 "일반"클래스보다 더 많은 유연성을 가질 수 있다는 것이 합리적이라는 것입니다.

귀하의 경우, 수업이 서로의 내부 작업을 볼 수 있다는 것은 의미가 없다면, 이는 기본적으로 내부 수업이 단순히 정규 수업으로 만들어 졌다는 것을 의미합니다. 내면의 클래스를 다음과 같이 선언 할 수 있습니다. static class XYZ. 사용 static 그들이 상태를 공유하지 않을 것임을 의미합니다 (예 : new ABC().new XYZ() 작동하지 않으며 사용해야합니다 new ABC.XYZ().
그러나 그럴 경우, 당신은 XYZ 실제로 내면의 클래스 여야하며 아마도 자체 파일이 필요할 수도 있습니다. 때로는 정적 내부 클래스를 만드는 것이 합리적입니다 (예 : 외부 클래스가 사용하는 인터페이스를 구현하는 작은 클래스가 필요한 경우 다른 곳에서는 도움이되지 않습니다). 그러나 시간의 약 절반에 그것은 외부 클래스로 만들어 졌을 것입니다.

Thilo는 좋은 것을 추가했습니다 대답 첫 번째 질문으로 "이것이 어떻게 가능합니까?" 두 번째 질문에 대해 조금 자세히 설명하고 싶습니다. 왜이 행동이 허용됩니까?

우선,이 동작은 정의에 의해 정적이 아닌 중첩 유형 인 내부 클래스에만 허용된다는 것을 완벽하게 분명히합시다. 이 동작은 정적이어야하고 인스턴스 인스턴스를 가질 수없는 중첩 열거 및 인터페이스를 포함하여 모든 중첩 유형에 대해 허용됩니다. 기본적 으로이 모델은 다음과 같은 설명으로 간단합니다. 중첩 코드는 코드를 둘러싸고 있으며 그 반대도 마찬가지입니다.

그렇다면 왜? 나는 그 예가 요점을 더 잘 보여준다고 생각합니다.

당신의 몸과 뇌를 생각하십시오. 팔에 헤로인을 주입하면 뇌가 높아집니다. 뇌의 편도체 영역이 자신이 개인적으로 안전에 위협이된다고 생각하는 것을 보면, 예를 들어 말벌을 말하십시오.

따라서 뇌는 신체의 본질적인 부분이며 이상하게도 다른 방법으로도 충분합니다. 밀접하게 관련된 엔티티 간의 액세스 제어를 사용하면 관계에 대한 주장을 상실합니다. 액세스 컨트롤이 필요한 경우 클래스를 진정으로 별개의 단위로 분리해야합니다. 그때까지 그들은 같은 단위입니다. 추가 연구를위한 운전 사례는 Java가 어떻게 Iterator 일반적으로 구현됩니다.

코드를 둘러싸는 코드에서 중첩 코드에 이르기까지 무제한 액세스는 대부분 중첩 유형의 필드 및 메소드에 액세스 수정자를 추가하는 데 쓸모가 없습니다. 그렇게하는 것은 혼란을 더하는 것이며 Java 프로그래밍 언어의 새로운 사람들에게 잘못된 안전감을 제공 할 수 있습니다.

내부 클래스는 외부 클래스의 속성으로 간주됩니다. 따라서 내부 클래스 인스턴스 변수가 개인이든 아니든 외부 클래스는 다른 개인 속성 (변수)에 액세스하는 것과 같은 문제없이 액세스 할 수 있습니다.

class Outer{

private int a;

class Inner{
private int b=0;
}

void outMethod(){
a = new Inner().b;
}
}

당신의 main() 메소드는 안에 있습니다 ABC 클래스 ~할 수 있다 자체 내부 클래스에 액세스하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top