Objeto de classe interna
Não consegui entender o comportamento do código abaixo.
Minha expectativa era que ele deveria imprimir 100 em ambos os println()métodos. Por que o resultado é diferente?
Se eu remover o comentário do getX()método na classe interna, a saída dos println(métodos) será a mesma, que é 100.
Eu não conseguia entender o raciocínio de um comportamento diferente. Por favor me ajude a entender.
public class Foo {
public static void main(String[] args) {
MyOuter outerObj = new MyOuter();
MyOuter.MyInner innerObj = outerObj.new MyInner();
innerObj.setX();
System.out.println("x: " + innerObj.getX()); //x: 3
System.out.println("x: " + outerObj.getX()); //x: 100
}
}
class MyOuter {
private int x = 3;
public int getX() { return x; }
class MyInner extends MyOuter {
public void setX(){ x = 100; }
// public int getX() { return x; }
}
}
Respostas
Da MyInnerperspectiva de, existem dois private int xcampos em jogo aqui:
- Um campo
super.xque é herdado deMyOuter, mas inacessível porque foi declarado comoprivateeMyInnercomo um objeto herdado não pode acessar este campo. - Um campo
MyOuter.this.xdo sorroundingMyOuter-instance (uma vez queMyInneré uma (não-estático) classe interna, que está sempre ligado a uma instância da envolventeMyOuter), que é acessível.
O método setX()em MyInnernão pode acessar o campo herdado super.x, portanto, ele acessa o campo MyOuter.this.xe define seus valores para 100. Uma chamada consecutiva nos cercam MyOuter's getX()vai voltar 100.
A chamada innerObj.getX()(que é herdada de MyOutere pode acessar super.x) retorna o valor do campo herdado super.x(ainda com seu valor inicial de 3).
Se removermos o extends MyOuterfrom e incluirmos o getX()método -in MyInner, o código se comportará conforme o esperado.
O fato de MyInnernão poder acessar o campo herdado private xé confuso no início, mas o comportamento está realmente alinhado com o comportamento da palavra-chave protectedno contexto de métodos estáticos em classes herdadas, conforme discutido neste post de Hariharan