Item 65: Dê preferência às interfaces em vez da reflexão
Java Efetivo (livro)
Posted on October 24, 2024
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);
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);
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.
Posted on October 24, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 28, 2024