outer - nested class java




Por que as classes Java externas podem acessar membros privados da classe interna? (7)

A classe interna é (para fins de controle de acesso) considerada como parte da classe que a contém. Isso significa acesso total a todos os privates.

A maneira como isso é implementado está usando métodos sintéticos protegidos por pacotes: A classe interna será compilada para uma classe separada no mesmo pacote (ABC $ XYZ). A JVM não suporta esse nível de isolamento diretamente, de modo que no nível de bytecode ABC $ XYZ terá métodos protegidos por pacote que a classe externa usa para obter os métodos / campos privados.

Observei que as classes externas podem acessar variáveis ​​de instâncias privadas de classes internas. Como isso é possível? Aqui está um código de exemplo demonstrando o mesmo:

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

Por que esse comportamento é permitido?


A classe interna é apenas uma maneira de separar de forma limpa algumas funcionalidades que realmente pertencem à classe externa original. Eles devem ser usados ​​quando você tem dois requisitos:

  1. Alguma parte da funcionalidade em sua classe externa seria mais clara se fosse implementada em uma classe separada.
  2. Mesmo estando em uma classe separada, a funcionalidade está muito ligada à maneira como a classe externa funciona.

Dados esses requisitos, as classes internas têm acesso total à sua classe externa. Como eles são basicamente um membro da classe externa, faz sentido que eles tenham acesso a métodos e atributos da classe externa - incluindo privates.


A lógica por trás das classes internas é que, se você criar uma classe interna em uma classe externa, é porque elas precisarão compartilhar algumas coisas e, portanto, faz sentido que elas tenham mais flexibilidade do que as classes "comuns".

Se, no seu caso, não faz sentido para as classes serem capazes de ver o funcionamento interno do outro - o que basicamente significa que a classe interna poderia simplesmente ter sido transformada em uma classe regular, você pode declarar a classe interna como static class XYZ . Usar static significa que eles não compartilharão o estado (e, por exemplo, o new ABC().new XYZ() não funcionará e você precisará usar o new ABC.XYZ() .
Mas, se for esse o caso, você deve pensar se o XYZ deve realmente ser uma classe interna e que talvez mereça seu próprio arquivo. Às vezes, faz sentido criar uma classe interna estática (por exemplo, se você precisar de uma pequena classe que implemente uma interface que sua classe externa esteja usando e que não será útil em nenhum outro lugar). Mas em cerca de metade do tempo deveria ter sido feito uma aula externa.



Restrições de acesso são feitas por turma. Não há como um método declarado em uma classe não conseguir acessar todos os membros da instância / classe. É lógico que as classes internas também tenham acesso irrestrito aos membros da classe externa, e a classe externa tenha acesso irrestrito aos membros da classe interna.

Ao colocar uma turma dentro de outra turma, você está firmemente vinculada à implementação, e qualquer coisa que faça parte da implementação deve ter acesso às outras partes.


Se você gosta de esconder os membros privados da sua classe interna, você pode definir uma interface com os membros públicos e criar uma classe interna anônima que implemente essa interface. Exemplo abaixo:

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

Um importante caso de uso da IMHO para classes internas é o padrão de fábrica. A classe envolvente pode preparar uma instância da classe interna sem restrições de acesso e passar a instância para o mundo externo, onde o acesso privado será honrado.

Em contradição ao abyx declarar que a classe estática não altera as restrições de acesso à classe envolvente, como mostrado abaixo. Além disso, as restrições de acesso entre classes estáticas na mesma classe de inclusão estão funcionando. Eu estava surpreso ...

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




private-members