Acabei de encontrar uma interface aninhada estática em nossa base de código.
class Foo {
public static interface Bar {
/* snip */
}
/* snip */
}
Eu nunca vi isso antes. O desenvolvedor original está fora de alcance. Portanto, eu tenho que perguntar SO:
Quais são as semânticas por trás de uma interface estática? O que mudaria se eu removesse o static
? Por que alguém faria isso?
Respostas:
A palavra-chave estática no exemplo acima é redundante (uma interface aninhada é automaticamente "estática") e pode ser removida sem afetar a semântica; Eu recomendaria que fosse removido. O mesmo vale para "público" nos métodos de interface e "público final" nos campos de interface - os modificadores são redundantes e apenas adicionam confusão ao código-fonte.
De qualquer forma, o desenvolvedor está simplesmente declarando uma interface chamada Foo.Bar. Não há associação adicional com a classe envolvente, exceto que o código que não pode acessar o Foo também não poderá acessar o Foo.Bar. (Do código-fonte - o bytecode ou o reflexo podem acessar o Foo.Bar, mesmo que o Foo seja privado de pacotes!)
É um estilo aceitável criar uma interface aninhada dessa maneira, se você espera que ela seja usada apenas a partir da classe externa, para que você não crie um novo nome de nível superior. Por exemplo:
fonte
A pergunta foi respondida, mas um bom motivo para usar uma interface aninhada é se sua função estiver diretamente relacionada à classe em que está. Um bom exemplo disso é a
Listener
. Se você tivesse uma classeFoo
e desejasse que outras classes pudessem ouvir eventos nela, poderia declarar uma interface com o nomeFooListener
ok, mas provavelmente seria mais claro declarar uma interface aninhada e implementar essas outras classesFoo.Listener
( uma classe aninhadaFoo.Event
não é ruim junto com isso).fonte
java.util.Map.Entry
(que é uma interface aninhada em outra interface).Map.Entry
) ou classes também dentro desse pacote. Digo isso porque gosto de manter minhas aulas curtas e objetivas. Além disso, um leitor pode ver quais outras entidades estão relacionadas a uma classe observando as classes no pacote. Eu provavelmente teria um pacotejava.collections.map
para mapas. Trata-se de OO e modularidade.java.util
tem muito nele.util
é comocommon
- um cheiro IMOjava.util
certamente tem muito nele. Dito isso, não acho que seja ideal dividi-lo em pacotes refinados, como você sugere.java.util.MapEntry
fora de seu próprio pacote. Primeiro reflexo: quais são as interfaces relacionadas a essa classe? Eu olho para a classe. A menos que o javadoc esteja vinculado a essa interface, não tenho idéia de sua relação. Além disso, as pessoas não olham para o pacote de importação. Todo mundo tem opiniões próprias. Ninguém está certo, ninguém está erradoAs interfaces dos membros são implicitamente estáticas. O modificador estático no seu exemplo pode ser removido sem alterar a semântica do código. Consulte também a Java Language Specification 8.5.1. Declarações de tipo de membro estático
fonte
Uma interface interna deve ser estática para ser acessada. A interface não está associada a instâncias da classe, mas à própria classe, portanto, seria acessada com
Foo.Bar
:De muitas maneiras, isso não é diferente de uma classe interna estática.
fonte
The interface isn't associated with instances of the class, but with the class itself
mais ainda, eu não consegui-loA resposta de Jesse é próxima, mas acho que existe um código melhor para demonstrar por que uma interface interna pode ser útil. Veja o código abaixo antes de ler. Você consegue descobrir por que a interface interna é útil? A resposta é que a classe DoSomethingAlready pode ser instanciada com qualquer classe que implemente A e C; não apenas a classe concreta Zoo. Obviamente, isso pode ser alcançado mesmo que a CA não seja interna, mas imagine concatenar nomes mais longos (não apenas A e C), e faça isso para outras combinações (por exemplo, A e B, C e B, etc.) e você facilmente veja como as coisas saem de controle. Sem mencionar que as pessoas que revisam sua árvore de origem serão sobrecarregadas por interfaces que são significativas apenas em uma classe.uma interface interna permite a construção de tipos personalizados e melhora seu encapsulamento .
fonte
Zoo
que não implementar a interfaceAC
, portanto, os casos deZoo
não pode ser passado para o construtor doDoSomethingAlready
que esperaAC
. O fato deAC
estender ambosA
eC
não implica que as classes sejam implementadasA
eC
magicamente também sejam implementadasAC
.Para responder sua pergunta diretamente, consulte Map.Entry.
Map.Entry
também isso pode ser útil
Entrada do blog Static Nested Inerfaces
fonte
Normalmente, vejo classes internas estáticas. Classes internas estáticas não podem fazer referência às classes que contêm, enquanto classes não estáticas podem. A menos que você esteja enfrentando algumas colisões de pacotes (já existe uma interface chamada Bar no mesmo pacote que o Foo), acho que seria o próprio arquivo. Também poderia ser uma decisão de design para impor a conexão lógica entre Foo e Bar. Talvez o autor pretenda que o Bar seja usado apenas com Foo (embora uma interface interna estática não imponha isso, apenas uma conexão lógica)
fonte
Se você mudar a classe Foo para a interface Foo, a palavra-chave "public" no exemplo acima também será redundante porque
fonte
Em 1998, Philip Wadler sugeriu uma diferença entre interfaces estáticas e não estáticas.
Por exemplo, ele propôs uma solução para o Problema da Expressão , que é a incompatibilidade entre expressão como "quanto sua linguagem pode expressar", por um lado, e expressão como "os termos que você está tentando representar em sua linguagem", por outro lado. .
Um exemplo da diferença entre interfaces aninhadas estáticas e não estáticas pode ser visto em seu código de amostra :
Sua sugestão nunca chegou ao Java 1.5.0. Portanto, todas as outras respostas estão corretas: não há diferença para interfaces aninhadas estáticas e não estáticas.
fonte
Em Java, a interface / classe estática permite que a interface / classe seja usada como uma classe de nível superior, ou seja, pode ser declarada por outras classes. Então, você pode fazer:
Sem o estático, o acima falharia ao compilar. A vantagem disso é que você não precisa de um novo arquivo de origem apenas para declarar a interface. Também associa visualmente a interface Bar à classe Foo, já que você precisa escrever Foo.Bar e implica que a classe Foo faz algo com instâncias de Foo.Bar.
Uma descrição dos tipos de classe em Java .
fonte
Estático significa que qualquer parte da classe do pacote (projeto) pode acessá-lo sem usar um ponteiro. Isso pode ser útil ou dificultar dependendo da situação.
O exemplo perfeito das utilidades dos métodos "estáticos" é a classe Math. Todos os métodos em matemática são estáticos. Isso significa que você não precisa sair do seu caminho, criar uma nova instância, declarar variáveis e armazená-las em ainda mais variáveis; basta digitar seus dados e obter um resultado.
A estática nem sempre é útil. Se você estiver comparando casos, por exemplo, convém armazenar dados de várias maneiras diferentes. Você não pode criar três métodos estáticos com assinaturas idênticas. Você precisa de 3 instâncias diferentes, não estáticas e, em seguida, é possível comparar e, se for estático, os dados não serão alterados junto com a entrada.
Os métodos estáticos são bons para retornos únicos e cálculos rápidos ou dados facilmente obtidos.
fonte