Pergunta

Acabei de encontrar uma interface estática aninhada 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, tenho que perguntar SO:

Qual é a semântica por trás de uma interface estática?O que mudaria se eu removesse o static?Por que alguém faria isso?

Foi útil?

Solução

A palavra-chave static no exemplo acima é redundante (uma interface aninhada é automaticamente "estática") e pode ser removida sem efeito na semântica;Eu recomendaria que fosse removido.O mesmo vale para "public" em métodos de interface e "public final" em 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á mais associação com a classe envolvente, exceto que o código que não pode acessar Foo também não poderá acessar Foo.Bar.(Do código-fonte - bytecode ou reflexão pode acessar Foo.Bar mesmo se Foo for pacote privado!)

É um estilo aceitável criar uma interface aninhada dessa maneira se você espera que ela seja usada apenas na classe externa, para não criar um novo nome de nível superior.Por exemplo:

public class Foo {
    public interface Bar {
        void callback();
    }
    public static void registerCallback(Bar bar) {...}
}
// ...elsewhere...
Foo.registerCallback(new Foo.Bar() {
    public void callback() {...}
});

Outras dicas

A pergunta foi respondida, mas um bom motivo para usar uma interface aninhada é se sua função está diretamente relacionada à classe em que está.Um bom exemplo disso é um Listener.Se você tivesse uma aula Foo e você quisesse que outras classes pudessem escutar eventos nela, você poderia declarar uma interface chamada FooListener, o que é bom, mas provavelmente seria mais claro declarar uma interface aninhada e fazer com que essas outras classes implementassem Foo.Listener (uma classe aninhada Foo.Event não é ruim junto com isso).

As 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 especificação da linguagem Java 8.5.1.Declarações de tipo de membro estático

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 ela seria acessada com Foo.Bar, igual a:

public class Baz implements Foo.Bar {
   ...
}

Em muitos aspectos, isso não é diferente de uma classe interna estática.

A resposta de Jesse está 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 continuar lendo.Você consegue descobrir por que a interface interna é útil?A resposta é que a classe DoSomethingAlready pode ser instanciada com qualquer classe que implementa A e C;não apenas a classe concreta Zoo.Claro, isso pode ser conseguido mesmo que AC não seja interno, mas imagine concatenar nomes mais longos (não apenas A e C) e fazer isso para outras combinações (digamos, A e B, C e B, etc.) e você facilmente veja como as coisas ficam fora de controle.Sem mencionar que as pessoas que revisarem sua árvore de origem ficarão sobrecarregadas com interfaces que são significativas apenas em uma classe. Então, para resumir, uma interface interna permite a construção de tipos personalizados e melhora seu encapsulamento.

class ConcreteA implements A {
 :
}

class ConcreteB implements B {
 :
}

class ConcreteC implements C {
 :
}

class Zoo implements A, C {
 :
}

class DoSomethingAlready {
  interface AC extends A, C { }

  private final AC ac;

  DoSomethingAlready(AC ac) {
    this.ac = ac;
  }
}

Para responder sua pergunta diretamente, consulte Map.Entry.

Entrada do mapa

também isso pode ser útil

Entrada de blog de inerfaces estáticas aninhadas

Normalmente vejo classes internas estáticas.Classes internas estáticas não podem fazer referência às classes que as 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 Foo), acho que criaria seu 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 pretendesse que Bar fosse usado apenas com Foo (embora uma interface interna estática não imponha isso, apenas uma conexão lógica)

Se você mudar a classe Foo para a interface Foo, a palavra-chave "public" no exemplo acima também será redundante porque

interface definida dentro de outra interface irá implicitamente estático público.

Em 1998, Philip Wadler sugeriu uma diferença entre interfaces estáticas e interfaces não estáticas.

Até onde posso ver, a única diferença em tornar uma interface não estática é que agora ela pode incluir classes internas não estáticas;Portanto, a mudança não tornaria inválido nenhum programa Java existente.

Por exemplo, ele propôs uma solução para o Problema de 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 exemplo:

// This code does NOT compile
class LangF<This extends LangF<This>> {
    interface Visitor<R> {
        public R forNum(int n);
    }

    interface Exp {
        // since Exp is non-static, it can refer to the type bound to This
        public <R> R visit(This.Visitor<R> v);
    }
}

Sua sugestão nunca apareceu no Java 1.5.0.Portanto, todas as outras respostas estão corretas:não há diferença entre interfaces aninhadas estáticas e não estáticas.

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:

class Bob
{
  void FuncA ()
  {
    Foo.Bar foobar;
  }
}

Sem a estática, o acima não seria compilado.A vantagem disso é que você não precisa de um novo arquivo fonte apenas para declarar a interface.Ele também associa visualmente a interface Bar à classe Foo, já que você precisa escrever Foo.Bar e implica que a classe Foo faça algo com instâncias de Foo.Bar.

Uma descrição dos tipos de classe em Java.

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 da utilidade 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 se esforçar, criar uma nova instância, declarar variáveis ​​e armazená-las em ainda mais variáveis, basta inserir seus dados e obter um resultado.

A estática nem sempre é tão útil.Se você estiver fazendo uma comparação de casos, por exemplo, talvez queira 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 então você pode comparar, porque se for estático, os dados não mudarão junto com a entrada.

Os métodos estáticos são bons para retornos únicos e cálculos rápidos ou dados obtidos facilmente.

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