O que é reflexão e por que é útil?
Estou particularmente interessado em Java, mas presumo que os princípios sejam os mesmos em qualquer idioma.
java
reflection
terminology
Lehane
fonte
fonte
@Jailbreak
. Ele fornece acesso direto, com segurança de tipo , a campos, métodos privados etc. Deixe o compilador Java verificar seu código com segurança e deixe o Manifold gerar o acesso de reflexão subjacente para você. Saiba mais: manifold.systems/docs.html#type-safe-reflectionRespostas:
A reflexão do nome é usada para descrever o código que é capaz de inspecionar outro código no mesmo sistema (ou ele próprio).
Por exemplo, digamos que você tenha um objeto de tipo desconhecido em Java e gostaria de chamar um método 'doSomething', se houver algum. O sistema de digitação estática do Java não é realmente projetado para suportar isso, a menos que o objeto esteja em conformidade com uma interface conhecida, mas, usando reflexão, seu código pode olhar para o objeto e descobrir se ele possui um método chamado 'doSomething' e, em seguida, chamá-lo se você quer.
Portanto, para dar um exemplo de código disso em Java (imagine o objeto em questão):
Um caso de uso muito comum em Java é o uso com anotações. A JUnit 4, por exemplo, usará a reflexão para procurar nas suas classes os métodos marcados com a anotação @Test, e os chamará ao executar o teste de unidade.
Existem alguns bons exemplos de reflexão para você começar em http://docs.oracle.com/javase/tutorial/reflect/index.html
E, finalmente, sim, os conceitos são muito semelhantes em outras linguagens estaticamente tipadas que suportam reflexão (como C #). Em linguagens tipadas dinamicamente, o caso de uso descrito acima é menos necessário (já que o compilador permitirá que qualquer método seja chamado em qualquer objeto, falhando no tempo de execução se ele não existir), mas o segundo caso de procurar métodos marcados ou o trabalho de uma certa maneira ainda é comum.
Atualização de um comentário:
fonte
Method
,Constructor
,Modifier
,Field
,Member
, basicamente, aparentemente, todos, excetoClass
) estão dentro dojava.lang.*reflect*
pacote. Talvez o conceito "reflexão" inclua abrangente "introspecção de tipo" e modificação em tempo de execução?Por exemplo, todos os objetos em Java possuem o método
getClass()
, que permite determinar a classe do objeto, mesmo que você não o conheça em tempo de compilação (por exemplo, se você o declarou comoObject
) - isso pode parecer trivial, mas essa reflexão não é possível em linguagens menos dinâmicas comoC++
. Usos mais avançados permitem listar e chamar métodos, construtores, etc.A reflexão é importante, pois permite que você escreva programas que não precisam "saber" tudo em tempo de compilação, tornando-os mais dinâmicos, pois podem ser ligados em tempo de execução. O código pode ser gravado em interfaces conhecidas, mas as classes reais a serem usadas podem ser instanciadas usando a reflexão dos arquivos de configuração.
Muitas estruturas modernas usam extensivamente a reflexão por esse mesmo motivo. A maioria das outras linguagens modernas também usa a reflexão e, nas linguagens de script (como Python), elas são ainda mais integradas, pois parece mais natural no modelo de programação geral dessas linguagens.
fonte
C++
possui informações do tipo em tempo de execução. RTTIUm dos meus usos favoritos da reflexão é o método Java dump abaixo. Ele pega qualquer objeto como parâmetro e usa a API de reflexão Java para imprimir todos os nomes e valores de campos.
fonte
callCount
deve estar definido como zero. Seu valor é usado para determinar quantas guias devem preceder cada linha de saída: cada vez que o dump precisar despejar um "subobjeto", a saída será impressa como aninhada no pai. Esse método se mostra útil quando envolvido em outro. ConsidereprintDump(Object obj){ System.out.println(dump(obj, 0)); }
.Usos da Reflexão
O Reflection é comumente usado por programas que requerem a capacidade de examinar ou modificar o comportamento em tempo de execução de aplicativos em execução na máquina virtual Java. Este é um recurso relativamente avançado e deve ser usado apenas por desenvolvedores que tenham uma forte compreensão dos fundamentos da linguagem. Com essa ressalva, a reflexão é uma técnica poderosa e pode permitir que os aplicativos realizem operações que, de outra forma, seriam impossíveis.
Recursos de extensibilidade
Um aplicativo pode fazer uso de classes externas definidas pelo usuário, criando instâncias de objetos de extensibilidade usando seus nomes totalmente qualificados. Navegadores de classe e ambientes de desenvolvimento visual Um navegador de classe precisa ser capaz de enumerar os membros das classes. Os ambientes de desenvolvimento visual podem se beneficiar do uso de informações de tipo disponíveis na reflexão para ajudar o desenvolvedor a escrever o código correto. Depuradores e Ferramentas de Teste Os depuradores precisam poder examinar membros particulares nas classes. Os chicotes de teste podem fazer uso da reflexão para chamar sistematicamente APIs de um conjunto detectável definido em uma classe, para garantir um alto nível de cobertura de código em um conjunto de testes.
Desvantagens da Reflexão
A reflexão é poderosa, mas não deve ser usada indiscriminadamente. Se for possível executar uma operação sem usar reflexão, é preferível evitar usá-la. As seguintes preocupações devem ser lembradas ao acessar o código via reflexão.
Como a reflexão envolve tipos resolvidos dinamicamente, determinadas otimizações da máquina virtual Java não podem ser executadas. Conseqüentemente, as operações reflexivas têm desempenho mais lento do que suas contrapartes não refletivas e devem ser evitadas nas seções de código que são chamadas frequentemente em aplicativos sensíveis ao desempenho.
O Reflection requer uma permissão de tempo de execução que pode não estar presente quando executado em um gerenciador de segurança. Isso é importante para o código que precisa ser executado em um contexto de segurança restrito, como em um Applet.
Como a reflexão permite que o código execute operações que seriam ilegais no código não-reflexivo, como acessar campos e métodos privados, o uso da reflexão pode resultar em efeitos colaterais inesperados, que podem tornar o código disfuncional e destruir a portabilidade. O código reflexivo quebra as abstrações e, portanto, pode alterar o comportamento com as atualizações da plataforma.
fonte: a API de reflexão
fonte
A reflexão é um mecanismo essencial para permitir que um aplicativo ou estrutura funcione com código que talvez ainda não tenha sido gravado!
Tomemos, por exemplo, seu arquivo web.xml típico. Isso conterá uma lista de elementos de servlet, que contêm elementos de classe de servlet aninhados. O contêiner de servlet processará o arquivo web.xml e criará uma nova instância nova de cada classe de servlet por meio de reflexão.
Outro exemplo seria a API Java para análise XML (JAXP) . Onde um provedor de analisador XML é 'conectado' por meio de propriedades conhecidas do sistema, que são usadas para construir novas instâncias por meio de reflexão.
E, finalmente, o exemplo mais abrangente é o Spring, que usa reflexão para criar seus beans e pelo uso pesado de proxies
fonte
Nem todas as línguas apóiam a reflexão, mas os princípios geralmente são os mesmos nas línguas que a apóiam.
Reflexão é a capacidade de "refletir" na estrutura do seu programa. Ou mais concreto. Para examinar os objetos e as classes que você possui e recuperar programaticamente informações sobre os métodos, campos e interfaces que eles implementam. Você também pode ver coisas como anotações.
É útil em muitas situações. Em todos os lugares que você deseja poder conectar dinamicamente classes ao seu código. Muitos mapeadores relacionais de objetos usam reflexão para poder instanciar objetos de bancos de dados sem saber antecipadamente quais objetos eles usarão. As arquiteturas de plug-in são outro lugar em que a reflexão é útil. Ser capaz de carregar código dinamicamente e determinar se existem tipos que implementam a interface correta para uso como plug-in é importante nessas situações.
fonte
O Reflection permite instanciação de novos objetos, invocação de métodos e operações de obtenção / configuração de variáveis de classe dinamicamente em tempo de execução, sem ter conhecimento prévio de sua implementação.
No exemplo acima, o parâmetro nulo é o objeto no qual você deseja chamar o método. Se o método for estático, você fornecerá nulo. Se o método não for estático, ao invocar, você precisará fornecer uma instância MyObject válida em vez de nula.
O Reflection também permite acessar membros / métodos privados de uma classe:
.
java.lang.reflect
). Os metadados da classe podem ser acessados atravésjava.lang.Class
.O Reflection é uma API muito poderosa, mas pode desacelerar o aplicativo se usado em excesso, pois resolve todos os tipos em tempo de execução.
fonte
O Java Reflection é bastante poderoso e pode ser muito útil. O Java Reflection possibilita inspecionar classes, interfaces, campos e métodos em tempo de execução, sem saber os nomes das classes, métodos etc. em tempo de compilação. Também é possível instanciar novos objetos, chamar métodos e obter / definir valores de campo usando reflexão.
Um exemplo rápido do Java Reflection para mostrar como é o uso do reflexo:
Este exemplo obtém o objeto Class da classe chamada MyObject. Usando o objeto de classe, o exemplo obtém uma lista dos métodos nessa classe, itera os métodos e imprime seus nomes.
Exatamente como tudo isso funciona é explicado aqui
Edit : Depois de quase 1 ano, estou editando esta resposta, enquanto lia sobre reflexão, recebi mais alguns usos do Reflection.
Quando o contexto do Spring processar esse elemento <bean>, ele usará Class.forName (String) com o argumento "com.example.Foo" para instanciar essa classe.
Ele usará novamente a reflexão para obter o configurador apropriado para o elemento <property> e definir seu valor para o valor especificado.
Para métodos particulares,
Para campos particulares,
fonte
Exemplo:
Tomemos, por exemplo, um aplicativo remoto que fornece ao aplicativo um objeto que você obtém usando os Métodos da API. Agora, com base no objeto, você pode precisar executar algum tipo de cálculo.
O provedor garante que o objeto pode ser de três tipos e precisamos executar o cálculo com base em que tipo de objeto.
Portanto, podemos implementar em 3 classes, cada uma contendo uma lógica diferente. Obviamente, as informações do objeto estão disponíveis em tempo de execução; portanto, você não pode codificar estaticamente para executar a computação, portanto, a reflexão é usada para instanciar o objeto da classe que você precisa para executar a computação com base no objeto recebido do provedor.
fonte
instanceof
para determinar o tipo de objeto em tempo de execução?Exemplo simples de reflexão. Em um jogo de xadrez, você não sabe o que será movido pelo usuário em tempo de execução. reflexão pode ser usada para chamar métodos que já estão implementados em tempo de execução:
fonte
O Reflection é uma API usada para examinar ou modificar o comportamento de métodos, classes, interfaces em tempo de execução.
java.lang.reflect package
.Os pacotes
java.lang
ejava.lang.reflect
fornecem classes para reflexão de java.O Reflection pode ser usado para obter informações sobre -
Classe O
getClass()
método é usado para obter o nome da classe à qual um objeto pertence.Construtores O
getConstructors()
método é usado para obter os construtores públicos da classe à qual um objeto pertence.Métodos O
getMethods()
método é usado para obter os métodos públicos da classe à qual um objeto pertence.A API de reflexão é usada principalmente em:
IDE (ambiente de desenvolvimento integrado), por exemplo, Eclipse, MyEclipse, NetBeans etc.
Depurador e Ferramentas de Teste etc.
Vantagens de usar a reflexão:
Recursos de extensibilidade: um aplicativo pode fazer uso de classes externas definidas pelo usuário, criando instâncias de objetos de extensibilidade usando seus nomes totalmente qualificados.
Ferramentas de depuração e teste: os depuradores usam a propriedade de reflexão para examinar membros privados em classes.
Desvantagens:
Sobrecarga de desempenho: as operações reflexivas têm desempenho mais lento do que suas contrapartes não refletivas e devem ser evitadas nas seções de código que são chamadas com freqüência em aplicativos sensíveis ao desempenho.
Exposição de componentes internos: o código reflexivo quebra as abstrações e, portanto, pode alterar o comportamento com as atualizações da plataforma.
Ref: Reflexão Java javarevisited.blogspot.in
fonte
Conforme meu entendimento:
O Reflection permite que o programador acesse entidades no programa dinamicamente. ou seja, ao codificar um aplicativo se o programador não souber sobre uma classe ou seus métodos, ele pode fazer uso dessa classe dinamicamente (em tempo de execução) usando reflexão.
É freqüentemente usado em cenários em que o nome de uma classe muda frequentemente. Se essa situação surgir, é complicado para o programador reescrever o aplicativo e alterar o nome da classe repetidamente.
Em vez disso, usando a reflexão, é necessário se preocupar com a possibilidade de alterar o nome da classe.
fonte
Reflexão é um conjunto de funções que permite acessar as informações de tempo de execução do seu programa e modificá-lo (com algumas limitações).
É útil porque permite alterar o comportamento do tempo de execução, dependendo das meta informações do seu programa, ou seja, você pode verificar o tipo de retorno de uma função e alterar a maneira como lida com a situação.
Em C #, por exemplo, você pode carregar um assembly (uma .dll) em tempo de execução e examiná-lo, navegando pelas classes e executando ações de acordo com o que encontrou. Também permite criar uma instância de uma classe em tempo de execução, chamar seu método etc.
Onde isso pode ser útil? Não é útil o tempo todo, mas para situações concretas. Por exemplo, você pode usá-lo para obter o nome da classe para fins de log, criar dinamicamente manipuladores para eventos de acordo com o que está especificado em um arquivo de configuração e assim por diante ...
fonte
Eu só quero acrescentar algum ponto a tudo o que foi listado.
Com o Reflection API, você pode escrever um
toString()
método universal para qualquer objeto.É útil na depuração.
Aqui está um exemplo:
fonte
Reflexão é deixar o objeto ver sua aparência. Este argumento não parece ter nada a ver com reflexão. De fato, essa é a capacidade de "auto-identificação".
A própria reflexão é uma palavra para linguagens que carecem da capacidade de autoconhecimento e auto-detecção como Java e C #. Como eles não têm capacidade de autoconhecimento, quando queremos observar como é, precisamos ter outra coisa para refletir sobre como é. Excelentes linguagens dinâmicas como Ruby e Python podem perceber o próprio reflexo sem a ajuda de outras pessoas. Podemos dizer que o objeto de Java não pode perceber como se parece sem um espelho, que é um objeto da classe de reflexão, mas um objeto no Python pode percebê-lo sem um espelho. É por isso que precisamos de reflexão em Java.
fonte
Na página de documentação do java
AccessibleObject
permite a supressão das verificações de acesso, se necessárioReflectPermission
.As classes neste pacote, além de
java.lang.Class
acomodar aplicativos como depuradores, intérpretes, inspetores de objetos, navegadores de classe e serviços comoObject Serialization
eJavaBeans
que precisam acessar os membros públicos de um objeto de destino (com base em sua classe de tempo de execução) ou os membros declarados por uma dada classeInclui a seguinte funcionalidade.
Dê uma olhada neste link de documentação para os métodos expostos por
Class
classe.Deste artigo (de Dennis Sosnoski, Presidente da Sosnoski Software Solutions, Inc) e deste artigo (pdf de explorações de segurança):
Eu posso ver desvantagens consideráveis do que o uso do Reflection
Usuário de Reflexão:
Desvantagens da reflexão:
Abusos gerais:
Dê uma olhada nesta pergunta SE sobre o recurso de abuso de reflexão:
Como leio um campo privado em Java?
Resumo:
O uso inseguro de suas funções conduzidas de dentro de um código do sistema também pode facilmente levar ao comprometimento de um modo de segurança Java l. Portanto, use esse recurso com moderação
fonte
Woozle
examine outras classes na inicialização para ver quais possuem umRegisterAsWoozleHelper()
método estático e invoque todos os métodos encontrados com um retorno de chamada que eles podem usar para falarWoozle
sobre si mesmos, evitando precisa usar o Reflection enquanto, por exemplo, desserializa dados.Como o próprio nome sugere, ele reflete o que contém, por exemplo, método de classe, etc, além de fornecer recurso para chamar a criação de método dinamicamente em tempo de execução.
É usado por muitas estruturas e aplicativos sob a madeira para chamar serviços sem realmente conhecer o código.
fonte
O Reflection permite escrever códigos mais genéricos. Ele permite que você crie um objeto no tempo de execução e chame seu método no tempo de execução. Portanto, o programa pode ser feito altamente parametrizado. Também permite a introspecção do objeto e da classe para detectar suas variáveis e métodos expostos ao mundo exterior.
fonte
Reflection
tem muitos usos . O que eu estou mais familiarizado é ser capaz de criar código rapidamente.fonte
Eu quero responder a esta pergunta pelo exemplo. Antes de tudo, o
Hibernate
projeto usaReflection API
para gerarCRUD
instruções para reduzir o abismo entre o aplicativo em execução e o armazenamento de persistência. Quando as coisas mudam no domínio,Hibernate
é preciso saber sobre elas para persistir no armazenamento de dados e vice-versa.Alternativamente funciona
Lombok Project
. Apenas injeta código no momento da compilação, resultando na inserção de código nas classes de domínio. (Eu acho que é bom para getters e setters)Hibernate
escolhidoreflection
porque tem um impacto mínimo no processo de criação de um aplicativo.E do Java 7 temos
MethodHandles
, que funciona comoReflection API
. Nos projetos, para trabalhar com loggers, basta copiar e colar o próximo código:Porque é difícil cometer erros de digitação neste caso.
fonte
Como eu acho melhor explicar pelo exemplo e nenhuma das respostas parece fazer isso ...
Um exemplo prático do uso de reflexões seria um servidor de linguagem Java escrito em Java ou um servidor de linguagem PHP escrito em PHP, etc. O servidor de linguagem fornece suas habilidades de IDE como preenchimento automático, pular para definição, ajuda de contexto, tipos de dicas e muito mais. Para que todos os nomes de tags (palavras que podem ser preenchidas automaticamente) mostrem todas as correspondências possíveis à medida que você digita, o Servidor de Idiomas precisa inspecionar tudo sobre a classe, incluindo blocos de documentos e membros privados. Para isso, é necessário refletir a referida classe.
Um exemplo diferente seria um teste de unidade de um método privado. Uma maneira de fazer isso é criar uma reflexão e alterar o escopo do método para público na fase de configuração do teste. É claro que se pode argumentar que métodos privados não devem ser testados diretamente, mas esse não é o ponto.
fonte