DEV Community

Java Efetivo (livro)
Java Efetivo (livro)

Posted on

Item 65: Dê preferência às interfaces em vez da reflexão

Reflexão em Java (java.lang.reflect):
Através da reflexão, é possível:

  • Acessar programaticamente construtores, métodos e campos de classes arbitrárias.
  • Manipular classes e seus membros (construtores, métodos, campos) de maneira reflexiva, permitindo criar instâncias, invocar métodos e acessar campos.
  • Invocar métodos em objetos, mesmo que as classes não existam durante a compilação.

Desvantagens da Reflexão:
Perda de verificação de tipo em tempo de compilação:

  • Erros que normalmente seriam detectados na compilação só aparecerão em tempo de execução.
  • Exemplo: invocar reflexivamente um método inexistente ou inacessível pode gerar exceções em tempo de execução.

Código pesado e verboso:
Reflexão exige código mais complexo e menos legível.
Exemplo:

Method method = obj.getClass().getMethod("methodName");
method.invoke(obj, args);

Enter fullscreen mode Exit fullscreen mode

Desempenho inferior:

  • Invocação reflexiva de métodos é consideravelmente mais lenta do que a invocação normal.
  • Exemplo: em certos cenários, a reflexão pode ser até 11 vezes mais lenta que a invocação direta de métodos.

Aplicações da Reflexão:

  • Usada em ferramentas de análise de código, frameworks de injeção de dependências e service provider frameworks.
  • Mesmo nesses contextos, deve ser evitada quando possível devido às suas desvantagens.

Uso limitado da reflexão:
Técnica sugerida: use reflexão apenas para instanciar classes desconhecidas em tempo de compilação e referencie essas instâncias por meio de interfaces ou superclasses conhecidas.

Exemplo:
Programa que cria instâncias de Set, especificadas pela linha de comando:

Class<? extends Set<String>> cl = (Class<? extends Set<String>>) Class.forName(args[0]);
Constructor<? extends Set<String>> cons = cl.getDeclaredConstructor();
Set<String> s = cons.newInstance();
for (int i = 1; i < args.length; i++) {
    s.add(args[i]);
}
System.out.println(s);

Enter fullscreen mode Exit fullscreen mode

Desvantagens ilustradas no exemplo:
Exceções de tempo de execução:

  • O exemplo pode gerar até seis exceções diferentes em tempo de execução.
  • Essas exceções seriam capturadas em tempo de compilação se não fosse usada a reflexão.

Complexidade e verbosidade:

  • O exemplo requer 25 linhas de código para instanciar uma classe a partir de seu nome, enquanto uma chamada de construtor direta seria feita em apenas uma linha.

Advertência de cast não verificado:

  • No exemplo, há uma advertência legítima de cast não verificado, pois a classe especificada na linha de comando pode não ser uma implementação de Set.

Uso legítimo da reflexão:

  • Dependências dinâmicas: quando uma classe, método ou campo pode não existir em tempo de execução.
  • Exemplo: você pode usar reflexão para suportar múltiplas versões de um pacote sem quebrar a compatibilidade com versões anteriores.

Conclusão:
Reflexão é poderosa, mas apresenta muitas desvantagens.
Sempre que possível, use a reflexão apenas para instanciar objetos e acesse-os por meio de interfaces ou superclasses conhecidas em tempo de compilação.

Exemplo do livro:
Image description

Top comments (0)