Objeto de classe interna

Sep 19 2020

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

4 Turing85 Sep 19 2020 at 05:26

Da MyInnerperspectiva de, existem dois private int xcampos em jogo aqui:

  • Um campo super.xque é herdado de MyOuter, mas inacessível porque foi declarado como privatee MyInnercomo um objeto herdado não pode acessar este campo.
  • Um campo MyOuter.this.xdo sorrounding MyOuter -instance (uma vez que MyInneré uma (não-estático) classe interna, que está sempre ligado a uma instância da envolvente MyOuter), 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