Pergunta

Eu observei que as classes Outer pode acessar classes internas variáveis ??de instância privadas. Como isso é possível? Aqui está um exemplo de código demonstrando a mesma:

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

Porque é que este comportamento permitido?

Foi útil?

Solução

A classe interna é apenas uma maneira de separar limpa algumas funcionalidades que realmente pertence à classe original exterior. Destinam-se a ser usado quando você tem 2 requisitos:

  1. Alguns pedaço de funcionalidade em sua classe externa seria mais claro se ele foi implementado em uma classe separada.
  2. Mesmo que seja em uma classe separada, a funcionalidade está intimamente ligada à maneira que as obras classe externa.

Tendo em conta estes requisitos, classes internas têm acesso total a sua classe externa. Uma vez que eles são, basicamente, um membro da classe externa, faz sentido que eles têm acesso a métodos e atributos da classe externa -. Incluindo privates

Outras dicas

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

A classe interna é (para fins de controlo de acesso), consideradas como fazendo parte da classe que contém. Isso significa acesso completo a todos os privates.

A forma como isto é implementado usando métodos é protegido por pacotes sintéticos: A classe interna vai ser compilado para uma classe separada de uma mesma embalagem (ABC $ XYZ). Será que a JVM não suportam este nível de isolamento diretamente, de modo que no nível de bytecode ABC $ XYZ terá métodos protegidos por pacotes que os usos classe externa para chegar aos métodos / campos particulares.

Não há uma resposta correta aparecer em outra pergunta semelhante a este: por que o membro particular de uma classe aninhada ser acessados ??pelos métodos da classe encerrando?

Ele diz que não há uma definição de escopo privado em JLS - Determinar acessibilidade :

Caso contrário, se o membro ou construtor é declarado privado, seguida, o acesso é permitido se, e somente se ocorrer dentro do corpo da classe nível superior (§7.6) que inclui a declaração do membro ou construtor.

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

Em contradição com abyx declarar a classe estática não muda as restrições de acesso à classe delimitador, como mostrado abaixo. Também as restrições de acesso entre classes estáticas na mesma classe delimitador estão trabalhando. Fiquei 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);
    }
}

As restrições de acesso são feitas em uma base por classe. Não há nenhuma maneira de um método declarado em uma classe para não ser capaz de acessar todos os membros da instância / aula. É isso lógico que classes internas também têm acesso irrestrito aos membros da classe externa, ea classe exterior tem acesso irrestrito aos membros da classe interna.

Ao colocar uma classe dentro de outra classe que você está tornando-se firmemente ligada à implementação, e qualquer coisa que é parte da implementação devem ter acesso às outras partes.

A lógica por trás classes internas é que se você criar uma classe interna em uma classe externa, isso é porque eles terão de compartilhar algumas coisas, e, portanto, faz sentido para eles para ser capaz de ter mais flexibilidade do que "regular" classes têm.

Se, no seu caso, não faz sentido para as classes para ser capaz de ver uns dos outros trabalhos internos - que basicamente significa que a classe interna poderia simplesmente ter sido feita uma classe regular, você pode declarar a classe interna como static class XYZ . Usando static significa que eles não vão estado share (e, por exemplo new ABC().new XYZ() não vai funcionar, e você vai precisar usar new ABC.XYZ().
Mas, se esse for o caso, você deve pensar se XYZ deve realmente ser uma classe interna e que talvez ele merece seu próprio arquivo. Às vezes faz sentido criar uma classe interna estático (por exemplo, se você precisar de uma pequena classe que implementa uma interface sua classe externa está usando, e que não vai ser em qualquer lugar útil mais). Mas em cerca de metade do tempo que deveria ter sido feita uma classe externa.

Thilo acrescentou uma boa resposta para sua primeira pergunta "Como isso é possível?". Desejo elaborar um pouco sobre o segundo perguntou pergunta: Porque é que este comportamento permitido

Para começar, vamos ser perfeitamente claro que este comportamento não é permitido somente para classes internas que por definição é tipos aninhados não-estáticos. Este comportamento é permitido para todos os tipos aninhados, incluindo enums aninhados e as interfaces que devem ser estáticos e não pode ter uma instância de inclusão. Basicamente, o modelo é uma simplificação para baixo para a seguinte declaração:. Código aninhada tem acesso total ao código anexando - e vice-versa

Então, por que então? Eu acho que um exemplo ilustrar o ponto melhor.

Pense no seu corpo e seu cérebro. Se você injetar heroína em seu braço, seu cérebro fica alta. Se a região da amígdala do cérebro ver o que ele acredita ser uma ameaça para a sua segurança pessoal, dizer uma vespa por exemplo, ele vai fazer o seu corpo para o outro caminho em volta e correr para as montanhas sem Você "pensamento" duas vezes sobre ele.

Assim, o cérebro é uma parte intrínseca do corpo - e curiosamente, o contrário também. Usando o controle de acesso entre tais entidades estreitamente relacionadas perder sua reivindicação de relacionamento. Se você fazer o controle de acesso necessidade, então você precisa separar as classes mais em unidades verdadeiramente distintas. Até então, eles são a mesma unidade. Um exemplo condução de novos estudos seria a de olhar como um Java Iterator geralmente é implementado.

Acesso ilimitado a partir encerrando código ao código aninhada torna, em sua maior parte, bastante inútil para adicionar modificadores de acesso aos campos e métodos de um tipo aninhado. Se o fizer, é a adição de desorganização e pode oferecer uma falsa sensação de segurança para os recém-chegados da linguagem de programação Java.

classe

Inner é considerado como um atributo da classe externa. Portanto, não importa a variável de instância de classe Inner é privado ou não, classe Outer acesso lata, sem qualquer problema, assim como acesso aos seus outros atributos privados (variáveis).

class Outer{

private int a;

class Inner{
private int b=0;
}

void outMethod(){
a = new Inner().b;
}
}

Como o seu método main() está na classe ABC, que pode acesso a sua própria classe interna.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top