Muitas pessoas podem não estar familiarizadas com as classes internas Java. Na verdade, existe um conceito semelhante em C++, ou seja, classes aninhadas. As diferenças e conexões entre os dois serão comparadas a seguir. Superficialmente, uma classe interna é apenas outra classe definida dentro da classe (como você verá abaixo, as classes internas podem ser definidas em muitos lugares), mas na verdade não é tão simples. À primeira vista, as classes internas parecem um pouco. redundante. A utilidade pode não ser tão óbvia para iniciantes, mas com uma compreensão mais profunda dela, você descobrirá que os designers de Java têm boas intenções em classes internas. Aprender a usar classes internas faz parte do domínio da programação Java avançada, que permite projetar a estrutura do seu programa com mais elegância. Vamos apresentá-lo a partir dos seguintes aspectos:
primeira reunião
Copie o código do código da seguinte forma:
interface pública Conteúdo {
valor interno();
}
interface pública Destino {
String readLabel();
}
bens de classe pública {
classe privada Conteúdo implementa Conteúdo {
privado int i = 11;
valor int público() {
retornar eu;
}
}
classe protegida GDestination implementa Destination {
rótulo de string privado;
private GDestination(String whereTo) {
rótulo = ondePara;
}
string pública readLabel() {
etiqueta de devolução;
}
}
destino público destino(String s) {
retornar novo(s) GDestination(s);
}
conteúdo público cont() {
retornar novo Conteúdo();
}
}
classe TestGoods {
public static void main(String[] args) {
Mercadorias p = novas Mercadorias();
Conteúdo c = p.cont();
Destino d = p.dest("Pequim");
}
}
Neste exemplo, as classes Content e GDestination são definidas dentro da classe Goods e possuem modificadores protected e private respectivamente para controlar os níveis de acesso. Conteúdo representa o conteúdo dos Bens e GDestination representa o destino dos Bens. Eles implementam duas interfaces Conteúdo e Destino respectivamente. No método principal a seguir, você usa diretamente Conteúdo c e Destino d para operar. Você nem vê os nomes dessas duas classes internas! Dessa forma, o primeiro benefício das classes internas é ocultar operações que você não deseja que outras pessoas saibam, ou seja, o encapsulamento.
Ao mesmo tempo, também descobrimos a primeira maneira de obter um objeto de classe interna fora do escopo da classe externa, que é criá-lo e retorná-lo usando os métodos de sua classe externa. Os métodos cont() e dest() no exemplo acima fazem isso. Então, existe alguma outra maneira?
Claro que existe,
o formato da sintaxe é o seguinte:
outerObject=new outerClass(Parâmetros do Construtor);
outerClass.innerClass innerObject=outerObject.new InnerClass (Parâmetros do Construtor);
Observe que ao criar um objeto de classe interna não estático, você deve primeiro criar o objeto de classe externa correspondente. Quanto ao motivo, isso leva ao nosso próximo tópico. Objetos de classe interna não estáticos têm referências a seus objetos de classe externa.
Modifique ligeiramente o exemplo anterior:
Copie o código do código da seguinte forma:
bens de classe pública {
private int taxa de valor = 2;
classe privada Conteúdo implementa Conteúdo {
private int i = 11 * taxa de valor;
valor int público() {
retornar eu;
}
}
classe protegida GDestination implementa Destination {
rótulo de string privado;
private GDestination(String whereTo) {
rótulo = ondePara;
}
string pública readLabel() {
etiqueta de devolução;
}
}
destino público destino(String s) {
retornar novo(s) GDestination(s);
}
conteúdo público cont() {
retornar novo Conteúdo();
}
}
Aqui adicionamos uma variável de membro privado valueRate à classe Goods, o que significa que o coeficiente de valor dos bens é multiplicado por ele quando o método value() da classe interna Content calcula o valor. Descobrimos que value() pode acessar valueRate, que é o segundo benefício das classes internas. Um objeto de classe interna pode acessar o conteúdo do objeto de classe externa que o criou, até mesmo variáveis privadas! Este é um recurso muito útil que nos fornece mais ideias e atalhos na hora de projetar. Para realizar esta função, o objeto da classe interna deve ter uma referência ao objeto da classe externa. Quando o compilador Java cria um objeto de classe interna, ele passa implicitamente a referência para seu objeto de classe externa e a mantém. Isso permite que o objeto da classe interna sempre acesse seu objeto da classe externa, e é também por isso que, para criar um objeto da classe interna fora do escopo da classe externa, você deve primeiro criar seu objeto da classe externa.
Algumas pessoas podem perguntar: o que devo fazer se uma variável de membro na classe interna tiver o mesmo nome que uma variável de membro na classe externa, ou seja, a variável de membro da classe externa com o mesmo nome estiver bloqueada? Tudo bem. Java usa o seguinte formato para expressar referências a classes externas:
outerClass.this
Com isso, não temos medo dessa situação de blindagem.
classe interna estática
Assim como as classes comuns, as classes internas também podem ser estáticas. No entanto, em comparação com classes internas não estáticas, a diferença é que as classes internas estáticas não possuem referências externas. Na verdade, isso é muito semelhante às classes aninhadas em C++. A maior diferença entre as classes internas Java e as classes aninhadas C++ é se há referências externas.
Além disso, em qualquer classe interna não estática, não pode haver dados estáticos, métodos estáticos ou outra classe interna estática (as classes internas podem ser aninhadas em mais de um nível). Mas você pode ter tudo isso em classes internas estáticas. Esta pode ser considerada a segunda diferença entre os dois.
classe interna local
Sim, as classes internas Java também podem ser locais, podem ser definidas dentro de um método ou mesmo de um bloco de código.
Copie o código do código da seguinte forma:
classe pública Mercadorias1 {
destino público destino(String s) {
classe GDestination implementa Destino {
rótulo de string privado;
private GDestination(String whereTo) {
rótulo = ondePara;
}
string pública readLabel() {
etiqueta de devolução;
}
}
retornar novo(s) GDestination(s);
}
public static void main(String[] args) {
Mercadoria1 g = nova Mercadoria1();
Destino d = g.dest("Pequim");
}
}
O acima é um exemplo. No método dest, definimos uma classe interna e, finalmente, este método retorna o objeto desta classe interna. Se precisarmos apenas criar um objeto de uma classe interna e criá-lo para fora, podemos fazer isso. É claro que as classes internas definidas nos métodos podem diversificar o design, e seus usos não se limitam a isso.
Aqui está um exemplo ainda mais estranho:
Copie o código do código da seguinte forma:
classe pública Mercadorias2 {
private void internalTracking(boolean b) {
se (b) {
classe TrackingSlip {
id de string privado;
TrackingSlip(Strings) {
id = s;
}
String getSlip() {
identificação de retorno;
}
}
TrackingSlip ts = new TrackingSlip("deslizamento");
String s = ts.getSlip();
}
}
public void faixa() {
internalTracking(verdadeiro);
}
public static void main(String[] args) {
Mercadorias2 g = novas Mercadorias2();
g.track();
}
}
Você não pode criar um objeto desta classe interna fora do if, porque isso vai além do seu escopo. Porém, durante a compilação, a classe interna TrackingSlip é compilada ao mesmo tempo que outras classes, exceto que possui seu próprio escopo e é inválida além deste escopo.
classe interna anônima
As regras de sintaxe das classes internas anônimas do Java podem parecer um pouco estranhas, mas assim como os arrays anônimos, quando você só precisa criar um objeto de uma classe e não precisa de seu nome, o uso de classes internas pode fazer o código parecer conciso e claro. Suas regras de sintaxe são as seguintes:
new interfacename(){......} ou new superclassname(){......};
Vamos continuar com o exemplo abaixo:
Copie o código do código da seguinte forma:
classe pública Mercadorias3 {
conteúdo público cont() {
retornar novo conteúdo() {
privado int i = 11;
valor int público() {
retornar eu;
}
};
}
}
O método cont() aqui usa uma classe interna anônima para retornar diretamente um objeto de uma classe que implementa a interface Contents, o que parece realmente muito simples.
Em adaptadores anônimos para processamento de eventos Java, classes internas anônimas são amplamente utilizadas. Por exemplo, quando quiser fechar a janela, adicione este código:
Copie o código do código da seguinte forma:
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
Sistema.exit(0);
}
});
Uma coisa a se notar é que como a classe interna anônima não tem nome, ela não tem construtor (mas se a classe interna anônima herdar uma classe pai que contém apenas um construtor parametrizado, ela deve trazer esses parâmetros ao criá-la, e usar o super palavra-chave para chamar o conteúdo correspondente durante o processo de implementação). Se você deseja inicializar suas variáveis-membro, existem vários métodos:
Se estiver em uma classe interna anônima de um método, você pode usar esse método para passar os parâmetros desejados, mas lembre-se, esses parâmetros devem ser declarados como finais.
Transforme a classe interna anônima em uma classe interna local nomeada para que ela possa ter um construtor.
Use um bloco de inicialização nesta classe interna anônima.
Por que você precisa de classes internas?
Quais são os benefícios das classes internas Java? Por que você precisa de classes internas?
Primeiro, vamos dar um exemplo simples. Se você deseja implementar uma interface, mas um método nesta interface tem o mesmo nome e parâmetros de um método na classe que você concebeu, o que você deve fazer? Neste momento, você pode construir uma classe interna para implementar esta interface. Como a classe interna é acessível a tudo na classe externa, isso realizará todas as funcionalidades que você teria se implementasse a interface diretamente.
Mas você pode querer questionar, não bastaria apenas mudar o método?
Na verdade, usar isso como razão para projetar classes internas não é realmente convincente.
A verdadeira razão é esta. Juntas, as classes e interfaces internas em Java podem resolver um problema do qual os programadores C++ frequentemente reclamam em Java sem herança múltipla. Na verdade, a herança múltipla de C++ é muito complicada de projetar, e Java pode alcançar muito bem o efeito de herança múltipla por meio de classes e interfaces internas.