Observei que as classes externas podem acessar variáveis de instância privada 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?
new ABC().new XYZ()
Respostas:
A classe interna é apenas uma maneira de separar claramente algumas funcionalidades que realmente pertencem à classe externa original. Eles devem ser usados quando você tiver 2 requisitos:
Dado esses requisitos, as classes internas têm acesso total à sua classe externa. Como eles são basicamente membros da classe externa, faz sentido que eles tenham acesso a métodos e atributos da classe externa - incluindo privados.
fonte
Se você deseja ocultar os membros privados de 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:
fonte
x
seja público aqui, não é permitidomMember.x
.A classe interna é (para fins de controle de acesso) considerada parte da classe que o contém. Isso significa acesso total a todos os particulares.
A maneira como isso é implementado é usando métodos sintéticos protegidos por pacote: A classe interna será compilada em 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 do bytecode, ABC $ XYZ terá métodos protegidos por pacote que a classe externa usa para acessar os métodos / campos privados.
fonte
Há uma resposta correta aparecendo em outra pergunta semelhante a esta: Por que o membro particular de uma classe aninhada pode ser acessado pelos métodos da classe envolvente?
Ele diz que há uma definição de escopo privado no JLS - Determinando a Acessibilidade :
fonte
Um caso de uso importante 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á respeitado.
Em contradição com a declaração abyx da classe static, 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 anexa estão funcionando. Eu estava surpreso ...
fonte
As restrições de acesso são feitas por classe. Não há como um método declarado em uma classe não poder 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 classe dentro de outra classe, você a está fortemente ligada à implementação, e qualquer coisa que faça parte da implementação deve ter acesso às outras partes.
fonte
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 possam ter mais flexibilidade do que as classes "regulares".
Se, no seu caso, não faz sentido que as classes possam ver o funcionamento interno uma da outra - o que basicamente significa que a classe interna poderia simplesmente ter se tornado uma classe regular, você pode declarar a classe interna como
static class XYZ
. Usarstatic
significa que eles não compartilharão o estado (e, por exemplonew ABC().new XYZ()
, não funcionarão, e você precisará usá-lonew ABC.XYZ()
.Mas, se for esse o caso, você deve pensar se
XYZ
realmente deve ser uma classe interna e que talvez mereça a sua). Às vezes, faz sentido criar uma classe interna estática (por exemplo, se você precisar de uma classe pequena que implemente uma interface que sua classe externa esteja usando e que não será útil em nenhum outro lugar) .Mas cerca da metade do tempo deveria ter sido feita uma classe externa.fonte
Thilo adicionou uma boa resposta para sua primeira pergunta "Como isso é possível?". Desejo elaborar um pouco sobre a segunda pergunta: por que esse comportamento é permitido?
Para iniciantes, vamos deixar perfeitamente claro que esse comportamento não se limita às classes internas, que por definição são tipos aninhados não estáticos. Esse comportamento é permitido para todos os tipos aninhados, incluindo enumerações e interfaces aninhadas, que devem ser estáticas e não podem ter uma instância anexa. Basicamente, o modelo é uma simplificação da seguinte declaração: Código aninhado tem acesso total ao código anexo - e vice-versa.
Então porque? Eu acho que um exemplo ilustra melhor o ponto.
Pense no seu corpo e no seu cérebro. Se você injetar heroína em seu braço, seu cérebro fica alto. Se a região da amígdala do seu cérebro vir o que ele acredita ser uma ameaça à sua segurança pessoal, digamos uma vespa, por exemplo, ele fará seu corpo se virar e correr para as colinas sem você "pensar" duas vezes.
Assim, o cérebro é uma parte intrínseca do corpo - e estranhamente, o contrário também. O uso do controle de acesso entre essas entidades estreitamente relacionadas perde a reivindicação de relacionamento. Se você precisar de controle de acesso, precisará separar as classes mais em unidades verdadeiramente distintas. Até então, eles são a mesma unidade. Um exemplo de direção para estudos adicionais seria examinar como um Java
Iterator
geralmente é implementado.O acesso ilimitado do código anexo ao código aninhado torna, na maioria das vezes, inútil adicionar modificadores de acesso aos campos e métodos de um tipo aninhado. Isso aumenta a confusão e pode fornecer uma falsa sensação de segurança para os novatos da linguagem de programação Java.
fonte
A classe interna é considerada como um atributo da classe externa. Portanto, independentemente da variável de instância da classe Inner ser privada ou não, a classe Outer pode acessar sem nenhum problema, assim como acessar seus outros atributos privados (variáveis).
fonte
Porque seu
main()
método está naABC
classe, que pode acessar sua própria classe interna.fonte
ABC
classe podem acessar classes aninhadas naABC
classe, mas por que eles podem acessar membros privados de classes aninhadas naABC
classe em Java.