Любопытно, почему для следующего кода
public class OuterClass{
int i;
public void printme(){
System.out.println("Outerclass");
i+=20;
System.out.println(i);
class InnerClass extends OuterClass {
public void printme(){
System.out.println("InnerClass");
i+=10;
System.out.println(i);
}
}
InnerClass second = new InnerClass();
second.printme();
System.out.println("Outerclass-2");
System.out.println(i);
return;
}
public static void main(String []args){
System.out.println("start");
OuterClass first = new OuterClass();
first.printme();
}
}
Выход
start Outerclass 20 InnerClass 10 Outerclass-2 20
Но если int я объявлен private, выход
start Outerclass 20 InnerClass 30 Outerclass-2 30
Может ли кто-нибудь объяснить?
Когда поле не имеет модификатора доступа, оно имеет видимость по умолчанию.
Из области InnerClass#printme()
, метод подкласса, он доступен. Так
i+=10;
обращается к InnerClass
экземпляра InnerClass
, который был инициализирован InnerClass
0.
private
поля не видны для подклассов, поэтому InnerClass
не может получить доступ к своим собственным. Но поскольку ваш InnerClass
является внутренним классом, который находится внутри тела OuterClass
он может получить доступ к закрывающему полю экземпляра. Так
i+=10;
обращается к OuterClass
экземпляра OuterClass
.
private
поле не может быть доступно в sub-class
но к нему можно получить доступ во внутреннем классе.
Поэтому, если у вас есть
int i;
// in InnerClass extends Outerclass
i += 10; // access the parent of this InnerClass
Однако
private int i;
// in InnerClass extends Outerclass
i += 10; // access the OuterClass as the parent is not accessible.
Конечно. Если он не является приватным, то его унаследовал InnerClass
то есть i
который работал on, является тем, что находится InnerClass
объекта InnerClass
. Если он является конфиденциальным, он не может быть унаследован, поэтому i
который работал, является тем, который находится в содержащем объекте.
InnerClass
не является строгим внутренним классом, который обычно известен из объявлений в классе. В этом случае это локальный класс и действительно является своего рода внутренним классом, но применяются совершенно разные правила. Эта проблема связана с наследованием и, следовательно, с переменными затенения.
В вашем случае, если вы расширяете класс с помощью модификатора по default
(none), вы можете получить доступ к этому полю и эффективно увидеть поле суперкласса.
Если поле объявлено как private
, то подкласс не может его видеть, но он имеет свой собственный, поскольку он расширяет ваш OutterClass
поэтому новый объект начинает со значения по умолчанию 0.
Посмотрите здесь, в части документации о Shadowing and local classes