Рассмотрим следующий код:

public class Foo
{
    class Bar
    {
        private String barbar;

        public Bar( String b ) { barbar = b; }
    }

    class Meh
    {
        Bar b = new Bar("BAR!");

        public void displayName() {
            System.out.println( b.barbar );
        }    
    }
}

Java позволяет классу Meh обращаться к частной переменной экземпляра barbar, которая объявлена ​​как private в Bar.

Я знаю, что этот вопрос был задан перед здесь. Однако ответ в основном повторяет, что наблюдаемая область видимости такова, какова она есть (что barbar доступна в фигурных скобках класса Foo), но не предлагает никаких объяснений. После некоторого поиска в Google мне так и не удалось найти хорошее обсуждение этого поведения. Что я хотел бы знать, так это то, есть ли какое-то конкретное обоснование такого поведения при определении объема работ. Я ожидал, что barbar будет закрытым "в фигурных скобках" класса Bar.

2
lurker 16 Окт 2015 в 15:55

4 ответа

Лучший ответ

Основным аспектом этого является то, что внутренние классы < / em> (в отличие от статических вложенных классов ) являются частью включающего их класса. Они неотделимы друг от друга или друг от друга. Таким образом, как и другие части включающего класса (конструкторы и методы), имеют доступ ко всей его частной информации, так же и все члены внутренних классов. Внутренние классы - это в некотором смысле фикция, которую мы используем в качестве удобного механизма абстракции. А поскольку внутренние классы являются частью включающего класса, их личная информация является его частной информацией, и поэтому используется совместно с другими внутренними классами.

5
T.J. Crowder 16 Окт 2015 в 13:00

Я не думаю, что вы сможете найти объяснение дизайна языка, если не поговорите с людьми, которые его разработали. Однако часто можно понять «почему» через Спецификацию языка Java. Раздел 6.3 (Объем декларации) < / a> устанавливает правила для определения области видимости и примеры правил в действии.

В частности, поведение, о котором вы спрашиваете, покрывается утверждением:

Область действия объявления локального класса, непосредственно заключенного в блок, - это остальная часть непосредственно включающего блока, включая его собственное объявление класса.

Два ваших локальных класса имеют одинаковую область видимости, то есть «непосредственно включающий блок», в частности класс Foo.

Возможно, в своем вопросе вы сможете объяснить, почему вы считаете, что barbar должен быть недоступен для включающего класса, и тогда мы сможем устранить любые ваши неправильные представления о том, как работает Java.

0
Paul 16 Окт 2015 в 13:23

Внутренний класс - это просто способ четко отделить некоторые функциональные возможности, которые действительно принадлежат исходному внешнему классу. Они предназначены для использования, когда у вас есть 2 требования:

Некоторая часть функциональности вашего внешнего класса была бы наиболее понятной, если бы она была реализована в отдельном классе. Несмотря на то, что он находится в отдельном классе, функциональность очень тесно связана с тем, как работает внешний класс. Учитывая эти требования, внутренние классы имеют полный доступ к своему внешнему классу. Поскольку они в основном являются членами внешнего класса, имеет смысл, что они имеют доступ к методам и атрибутам внешнего класса, включая частные.

1
lesnar 16 Окт 2015 в 12:59

Согласно JLS

В теле класса объявляются члены (поля и методы, а также вложенные классы и интерфейсы), экземпляры и статические инициализаторы, а также конструкторы. область действия члена - это все тело объявления класса, к которому член принадлежит. Поле, метод, класс члена, интерфейс члена и объявления конструктора могут включать модификаторы доступа общедоступный, защищенный или частный.

Итак, согласно примеру, класс Bar и класс Meh оба принадлежат классу Foo.

Следовательно, любой член Foo будет иметь доступ ко всем своим другим членам, независимо от его метода поля или вложенного класса / интерфейса в соответствии с первой строкой в ​​спецификациях.


Комментарий вопрос:

Если бы я сделал переменную внутри Bar как public вместо закрытой, стала бы она тогда доступной за пределами Foo, даже если она из внутреннего класса?

Да, конечно, это доступно извне. Посмотрите на пример ниже

class A {

    Foo foo = new Foo();
    Foo.Bar bar = foo.new Bar("name");

    public void someOtherMethod() {
        bar.barbar = "someOtherName"; 
        //this is valid only if barbar is public
        //or if it is default and within the same package
    }

}
2
rajuGT 16 Окт 2015 в 14:44