외부 Java 클래스가 내부 클래스 전용 멤버에 액세스 할 수있는 이유는 무엇입니까?
외부 클래스가 내부 클래스 전용 인스턴스 변수에 액세스 할 수 있음을 관찰했습니다. 이것이 어떻게 가능한지? 다음은 동일한 내용을 보여주는 샘플 코드입니다.
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??
}
}
이 동작이 왜 허용됩니까?
내부 클래스는 원래 외부 클래스에 속하는 일부 기능을 명확하게 분리하는 방법입니다. 다음 두 가지 요구 사항이있을 때 사용하도록 만들어졌습니다.
- 외부 클래스의 일부 기능은 별도의 클래스로 구현 된 경우 가장 분명합니다.
- 별도의 클래스에 있지만 기능은 외부 클래스의 작동 방식과 매우 밀접한 관련이 있습니다.
이러한 요구 사항이 주어지면 내부 클래스는 외부 클래스에 완전히 액세스 할 수 있습니다. 기본적으로 외부 클래스의 멤버이므로 개인을 포함하여 외부 클래스의 메서드 및 속성에 액세스 할 수 있습니다.
내부 클래스의 비공개 멤버를 숨기려면 공개 멤버와의 인터페이스를 정의하고이 인터페이스를 구현하는 익명의 내부 클래스를 만들 수 있습니다. 벨로우즈 예제 :
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의 중요한 사용 사례는 팩토리 패턴입니다. 엔 클로징 클래스는 액세스 제한이없는 내부 클래스의 인스턴스를 준비하고 인스턴스를 외부 세계로 전달할 수 있으며 개인 액세스는 존중됩니다.
모순에서 abyx은 아래 그림과 같이 클래스의 정적을 선언, 바깥 쪽 클래스에없는 변경 액세스 제한을한다. 또한 동일한 엔 클로징 클래스에서 정적 클래스 간의 액세스 제한이 작동 중입니다. 놀랐습니다 ...
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);
}
}
Access restrictions are done on a per class basis. There is no way for a method declared in a class to not be able to access all of the instance/class members. It this stands to reason that inner classes also have unfettered access to the members of the outer class, and the outer class has unfettered access to the members of the inner class.
By putting a class inside another class you are making it tightly tied to the implementation, and anything that is part of the implementation should have access to the other parts.
The logic behind inner classes is that if you create an inner class in an outer class, that's because they will need to share a few things, and thus it makes sense for them to be able to have more flexibility than "regular" classes have.
If, in your case, it makes no sense for the classes to be able to see each other's inner workings - which basically means that the inner class could simply have been made a regular class, you can declare the inner class as static class XYZ
. Using static
will mean they will not share state (and, for example new ABC().new XYZ()
won't work, and you will need to use new ABC.XYZ()
.
But, if that's the case, you should think about whether XYZ
should really be an inner class and that maybe it deserves its own file. Sometimes it makes sense to create a static inner class (for example, if you need a small class that implements an interface your outer class is using, and that won't be helpful anywhere else). But at about half of the time it should have been made an outer class.
Thilo added a good answer for your first question "How is this possible?". I wish to elaborate a bit on the second asked question: Why is this behavior allowed?
For starters, let's just be perfectly clear that this behavior is not only allowed for inner classes which by definition is non-static nested types. This behavior is allowed for all nested types, including nested enums and interfaces which must be static and cannot have an enclosing instance. Basically, the model is a simplification down to the following statement: Nested code have full access to enclosing code - and vice versa.
So, why then? I think an example illustrate the point better.
Think of your body and your brain. If you inject heroin into your arm, your brain gets high. If the amygdala region of your brain see what he believe is a threat to your personally safety, say a wasp for example, he'll make your body turn the other way around and run for the hills without You "thinking" twice about it.
So, the brain is an intrinsic part of the body - and strangely enough, the other way around too. Using access control between such closely related entities forfeit their claim of relationship. If you do need access control, then you need to separate the classes more into truly distinct units. Until then, they are the same unit. A driving example for further studies would be to look at how a Java Iterator
usually is implemented.
둘러싸는 코드에서 중첩 코드로의 무제한 액세스는 대부분 중첩 유형의 필드 및 메소드에 액세스 수정자를 추가하는 데 쓸모가 없습니다. 그렇게하면 혼란이 가중되고 Java 프로그래밍 언어의 새로운 사용자에게 잘못된 안전감을 제공 할 수 있습니다.
내부 클래스는 외부 클래스의 속성으로 간주됩니다. 따라서 내부 클래스 인스턴스 변수가 개인용이든 아니든 외부 클래스는 다른 개인용 속성 (변수)에 액세스하는 것처럼 문제없이 액세스 할 수 있습니다.
class Outer{
private int a;
class Inner{
private int b=0;
}
void outMethod(){
a = new Inner().b;
}
}
main()
메소드가 ABC
클래스 에 있기 때문에 자체 내부 클래스에 액세스 할 수 있습니다.
'Programing' 카테고리의 다른 글
LINQ를 사용하여 데이터를 피벗 할 수 있습니까? (0) | 2020.05.29 |
---|---|
CSV 파일을 SQL Server로 가져 오기 (0) | 2020.05.29 |
SQL Server 프로파일 러에서 "exec sp_reset_connection"은 무엇입니까? (0) | 2020.05.29 |
자식 인덱스에는 정확히 무엇이 포함되어 있습니까? (0) | 2020.05.29 |
TFS 소스 제어에서 여러 파일 이동 (0) | 2020.05.29 |