为什么外部 Java 类可以访问内部类私有成员?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1801718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:46:49  来源:igfitidea点击:

Why can outer Java classes access inner class private members?

javaclassprivateinner-classesprivate-members

提问by Harish

I observed that Outer classes can access inner classes private instance variables. How is this possible? Here is a sample code demonstrating the same:

我观察到外部类可以访问内部类私有实例变量。这怎么可能?这是演示相同内容的示例代码:

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??
    }
}

Why is this behavior allowed?

为什么允许这种行为?

采纳答案by Kaleb Brasee

The inner class is just a way to cleanly separate some functionality that really belongs to the original outer class. They are intended to be used when you have 2 requirements:

内部类只是一种将真正属于原始外部类的功能彻底分离的方法。它们旨在在您有 2 个要求时使用:

  1. Some piece of functionality in your outer class would be most clear if it was implemented in a separate class.
  2. Even though it's in a separate class, the functionality is very closely tied to way that the outer class works.
  1. 如果外部类中的某些功能在单独的类中实现,则它会最清楚。
  2. 即使它在一个单独的类中,其功能也与外部类的工作方式密切相关。

Given these requirements, inner classes have full access to their outer class. Since they're basically a member of the outer class, it makes sense that they have access to methods and attributes of the outer class -- including privates.

鉴于这些要求,内部类可以完全访问其外部类。由于它们基本上是外部类的成员,因此它们可以访问外部类的方法和属性——包括私有的。

回答by aberrant80

Because your main()method is in the ABCclass, which canaccess its own inner class.

因为你的main()方法在ABC类中,它可以访问自己的内部类。

回答by Thilo

The inner class is (for purposes of access control) considered to be part of the containing class. This means full access to all privates.

内部类(出于访问控制的目的)被视为包含类的一部分。这意味着完全访问所有私人。

The way this is implemented is using synthetic package-protected methods: The inner class will be compiled to a separate class in the same package (ABC$XYZ). The JVM does not support this level of isolation directly, so that at the bytecode-level ABC$XYZ will have package-protected methods that the outer class uses to get to the private methods/fields.

实现的方式是使用合成包保护方法:内部类将被编译为同一包中的单独类 (ABC$XYZ)。JVM 不直接支持这种隔离级别,因此在字节码级别 ABC$XYZ 将具有包保护的方法,外部类使用这些方法来获取私有方法/字段。

回答by TofuBeer

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.

通过将一个类放入另一个类中,您使其与实现紧密相关,并且任何属于实现的部分都应该可以访问其他部分。

回答by abyx

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 staticwill 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 XYZshould 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.

如果在您的情况下,类无法看到彼此的内部工作原理 - 这基本上意味着内部类可以简单地成为常规类,您可以将内部类声明为static class XYZ. 使用static将意味着它们不会共享状态(并且,例如new ABC().new XYZ()不会工作,您将需要使用new ABC.XYZ()
但是,如果是这种情况,您应该考虑是否XYZ应该真正成为内部类,也许它值得拥有自己的文件。有时创建一个静态内部类是有意义的(例如,如果您需要一个实现外部类正在使用的接口的小类,而这在其他任何地方都没有帮助)。但大约有一半的时间它应该是一个外部类。

回答by thomasfr

An IMHO important use case for inner classes is the factory pattern. The enclosing class may prepare an instance of the inner class w/o access restrictions and pass the instance to the outside world, where private access will be honored.

恕我直言,内部类的一个重要用例是工厂模式。封闭类可以准备一个没有访问限制的内部类的实例,并将该实例传递给外部世界,在那里私有访问将得到尊重。

In contradiction to abyxdeclaring the class static doesn't change access restrictions to the enclosing class, as shown below. Also the access restrictions between static classes in the same enclosing class are working. I was surprised ...

abyx声明类 static 不改变对封闭类的访问限制相反,如下所示。同一个封闭类中的静态类之间的访问限制也在起作用。我很惊讶 ...

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

回答by Ich

If you like to hide the private members of your inner class, you may define an Interface with the public members and create an anonymous inner class that implements this interface. Example bellow:

如果你想隐藏你的内部类的私有成员,你可以定义一个带有公共成员的接口,并创建一个实现这个接口的匿名内部类。示例如下:

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

回答by Colin Su

There's a correct answer appearing on another question similar to this: Why can the private member of an nested class be accessed by the methods of the enclosing class?

在另一个与此类似的问题上出现了正确答案: 为什么嵌套类的私有成员可以被封闭类的方法访问?

It says there's a definition of private scoping on JLS - Determining Accessibility:

它说JLS上有一个私有范围的定义- Determining Accessibility

Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

否则,如果成员或构造函数被声明为私有,则当且仅当它发生在包含成员或构造函数声明的顶级类(第 7.6 节)的主体内时,才允许访问。

回答by Martin Andersson

Thilo added a good answerfor your first question "How is this possible?". I wish to elaborate a bit on the second asked question: Why is this behavior allowed?

Thilo为您的第一个问题“这怎么可能?”添加了一个很好的答案。我想详细说明第二个问题:为什么允许这种行为?

For starters, let's just be perfectly clear that this behavior is not limited to inner classes, which by definition are 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 Iteratorusually is implemented.

所以,大脑是身体的一个内在部分——奇怪的是,反过来也是如此。在此类密切相关的实体之间使用访问控制会丧失其关系声明。如果您确实需要访问控制,那么您需要将类更多地分成真正不同的单元。在那之前,它们是同一个单位。进一步研究的一个驱动示例是查看 JavaIterator通常是如何实现的。

Unlimited access from enclosing code to nested code makes it, for the most part, rather useless to add access modifiers to fields and methods of a nested type. Doing so is adding clutter and might provide a false sense of safety for new comers of the Java programming language.

从封闭代码到嵌套代码的无限访问使得在大多数情况下向嵌套类型的字段和方法添加访问修饰符是无用的。这样做会增加混乱,并可能为 Java 编程语言的新手提供错误的安全感。

回答by MonMoonkey

Inner class is regarded as an attribute of the Outer class. Therefore, no matter the Inner class instance variable is private or not, Outer class can access without any problem just like accessing its other private attributes(variables).

内部类被视为外部类的一个属性。因此,无论 Inner 类实例变量是否私有,Outer 类都可以像访问其其他私有属性(变量)一样毫无问题地访问。

class Outer{

private int a;

class Inner{
private int b=0;
}

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