Skip to main content

Command Palette

Search for a command to run...

Noções básicas de reflexão

Published
7 min read
Noções básicas de reflexão
A

My name is Lucas. I'm a journalist and software developer who can take photos, print zines and make videos, that's no joke. 📸📰🎬💻🕺😅

A reflexão é um recurso poderoso em Java que permite ao programador examinar ou modificar a estrutura de uma classe em tempo de execução. Isso significa que um programa pode inspecionar e manipular seu próprio código, tornando a reflexão uma ferramenta útil para geração de código em tempo de execução, testes e muito mais.

A reflexão é um recurso poderoso em Java que permite ao programador examinar ou modificar a estrutura de uma classe em tempo de execução . Isso significa que um programa pode inspecionar e manipular seu próprio código, tornando a reflexão uma ferramenta útil para geração de código em tempo de execução, testes e muito mais.

Você pode imaginá-lo como algo semelhante à magia negra, pois é possível quebrar diversos princípios de design ao utilizá-lo. Mais importante ainda, você pode contornar o encapsulamento acessando campos de membros que não são expostos pela API pública. Em outras palavras, ele permite obter detalhes de implementação.

pacote java.lang.reflect

A reflexão em Java é implementada pelo pacote java.lang.reflect. Embora java.lang.reflect inclua muitas interfaces, classes e exceções, existem apenas quatro classes que você precisa conhecer neste nível. Essas classes são:

  • Field: você pode usá-lo para obter e modificar o nome, o valor, o tipo de dados e o modificador de acesso de uma variável.

  • Method: você pode usá-lo para obter e modificar o nome, o tipo de retorno, os tipos de parâmetros, o modificador de acesso e o tipo de exceção de um método.

  • Constructor: você pode usá-lo para obter e modificar o nome, os tipos de parâmetros e o modificador de acesso de um construtor.

  • Modifier: você pode usá-lo para obter informações sobre um modificador de acesso específico.

java.lang.Class

Há outro ponto importante. Você não consegue realizar reflexão apenas com o pacote Reflect que mencionamos acima. O pacote Reflect pode fornecer informações sobre um campo, método ou construtor de uma classe, mas primeiro você precisa obter a lista de campos, a lista de métodos e a lista de construtores.

Isso é possível com a classe e seu método estático java.lang.Class. Quando você passa o nome de qualquer classe para o método forName(), ele retorna um objeto do tipo Class que inclui informações sobre essa classe.

Outro método que retorna um objeto Class é getSuperclass() o método de instância. Este método retorna uma superclasse de uma instância de Class.

A classe java.lang.Class também possui diversos métodos que você pode usar para obter atributos (campos, métodos, construtores) da classe específica que você passou para o método forName(). Aqui estão alguns desses métodos:

  • getConstructors()

  • getDeclaredConstructors()

  • getFields()

  • getDeclaredFields()

  • getMethods()

  • getDeclaredMethods()

Há duas coisas importantes a saber sobre esses métodos.

Primeiramente, cada um desses métodos retorna um array de objetos de java.lang.reflectclasses. Por exemplo, getObject getFields()() retorna um array de objetos da java.lang.reflect.Fieldclasse Class. Depois disso, você pode usar os métodos do pacote java.lang.reflect para obter mais informações sobre construtores, campos e métodos.

Em segundo lugar, getConstructors()e getFields() getMethods()retornam apenas construtores, campos e métodos públicos da classe representada pelo objeto Class. Esses métodos também retornam campos e métodos públicos herdados das superclasses.

Da mesma forma, getDeclaredConstructors() getDeclaredFields(), getDeclaredMethods()retornam todos os construtores, campos e métodos da classe representada pelo objeto Class. Esses métodos não retornam campos e métodos herdados das superclasses.

Geralmente, os desenvolvedores usam métodos declarados com mais frequência do que métodos não declarados. Você entenderá melhor isso com um exemplo prático — vamos ver um agora!

Exemplos de codificação

Suponha que você tenha uma classe chamada Student. Ela possui três campos públicos, um campo protegido e um campo privado. Ela também possui um construtor padrão e um construtor público. A classe Student também possui um método privado e um método público.

public class Student {
    public String firstName;
    public String lastName;
    public int age;
    protected String phoneNumber;
    private String accountNumber;

    Student(){
        System.out.println("This is default Constructor");
    }

    public Student(String firstName, String lastName){
        this.firstName= firstName;
        this.lastName= lastName;
        System.out.println("This is public Constructor");
    }

    private String sanitizeAccountNumber(String accountNumber){
        System.out.println("This is a private method to sanitize account number");
        //code to sanitize accountNumber goes here. 
        return accountNumber;
    }

    public void setAccountNumber(String accountNumber){
        accountNumber = sanitizeAccountNumber(accountNumber);
        this.accountNumber = accountNumber;
    }
}Explique o código

O processo de reflexão geralmente tem três etapas:

1. Obtenha um objeto java.lang.Class da classe usando o método forName(). Neste caso, a classe que queremos refletir é Student.

Class student = Class.forName("Student");Explique o código

2. Obtenha os atributos da classe. Neste caso, estamos interessados ​​na superclasse, nos campos, nos construtores e nos métodos.

Class superclass = student.getSuperclass();
Constructor[] declaredConstructors = student.getDeclaredConstructors();
Constructor[] constructors = student.getConstructors();
Field[] declaredFields = student.getDeclaredFields();
Field[] fields = student.getFields();
Method[] declaredMethods = student.getDeclaredMethods();
Method[] methods = student.getMethods();Explique o código

3. Obtenha as informações sobre os atributos da classe e utilize-as. Neste caso, vamos recuperar os nomes da superclasse, dos construtores, dos campos e dos métodos e imprimi-los.

System.out.println("Superclass " + superclass);

for (Constructor dc : declaredConstructors) {
    System.out.println("Declared Constructor " + dc.getName());
}
for (Constructor c : constructors) {
    System.out.println("Constructor " + c.getName());
}
for (Field df : declaredFields) {
    System.out.println("Declared Field " + df.getName());
}
for (Field f : fields) {
    System.out.println("Field " + f.getName());
}
for (Method dm : declaredMethods) {
    System.out.println("Declared Method " + dm.getName());
}
for (Method m : methods) {
    System.out.println("Method " + m.getName());
}Explique o código

Você pode escrever essas três seções dentro do main()método e executar esse código.

Explicando a saída

Ao executar o código acima, você obterá o nome da superclasse, listas de construtores, campos e métodos:

Superclass class java.lang.Object
Declared Constructor Student
Declared Constructor Student
Constructor Student
Declared Field firstName
Declared Field lastName
Declared Field age
Declared Field phoneNumber
Declared Field accountNumber
Field firstName
Field lastName
Field age
Declared Method sanitizeAccountNumber
Declared Method setAccountNumber
Method setAccountNumber
Method wait
Method wait
Method wait
Method equals
Method toString
Method hashCode
Method getClass
Method notify
Method notifyAll

Você pode ver que getDeclaredConstructors() retornou ambos os construtores da classe Student, enquanto getConstructors() retornou apenas o construtor público. Da mesma forma, getDeclaredFields() retornou todos os campos da classe Student enquanto getFields() retornou apenas os campos públicos.

Finalmente, imprimimos os métodos da classe Student. Como esperado, getDeclaredMethods() retornou ambos os métodos. Agora, a parte interessante é que getMethods() retornou alguns métodos diferentes dos que setAccountNumber(). Se você se lembra, em um dos nossos tópicos anteriores, mencionamos que a classe java.lang.Object é a superclasse de todas as classes que criamos. A classe Object possui nove métodos públicos, e todas as classes que criamos herdam esses métodos. É por isso que você pode ver nove métodos extras na saída.

Riscos e desvantagens

Embora a reflexão ofereça recursos poderosos, ela deve ser usada com cautela. Utilize-a somente quando necessário e quando seus benefícios superarem suas possíveis desvantagens, que são:

  • Sobrecarga de desempenho: a reflexão pode adicionar uma sobrecarga significativa ao seu programa, exigindo processamento extra para inspecionar e manipular a estrutura do código em tempo de execução. Isso pode levar a um desempenho mais lento, especialmente em aplicações grandes e complexas.

  • Problemas de manutenção: a reflexão pode complicar a manutenção do código, pois o comportamento do código pode mudar dinamicamente em tempo de execução. Isso pode dificultar a compreensão de como o código está sendo usado e manipulado, levando a problemas de compatibilidade, dificultando atualizar ou alterar o código no futuro.

Para minimizar esses riscos, recomendamos limitar a reflexão a áreas específicas e bem definidas do código, idealmente dentro de frameworks e bibliotecas, onde ela pode ser usada para fornecer um alto nível de abstração e tornar o código mais flexível e reutilizável.

Conclusão

A reflexão é uma forma de obter informações sobre, ou modificar, campos, métodos e construtores de uma classe. O pacote java.lang.reflect e a java.lang.Class são essenciais na reflexão em Java.

O processo de reflexão em Java possui três etapas:

  1. Obtenha o objeto da classe sobre a qual você deseja realizar a reflexão.

  2. Obtenha os atributos da classe sobre a qual você deseja realizar a reflexão como uma lista ou matriz usando métodos de java.lang.Class

  3. Obtenha informações sobre o atributo específico que você obteve durante a segunda etapa usando o pacote java.lang.reflect.

Reflexão é um conceito avançado que requer algum conhecimento da JVM e dos processos internos do Java. De qualquer forma, acreditamos que as informações neste tópico ajudarão você a começar a usar reflexão em seus projetos!

More from this blog

A

Aú Desviante

53 posts

Estudos em Tecnologia e Desenvolvimento de Software