Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

Esta é uma postagem traduzida por IA.

제이온

[Java] Conceito e uso de reflexão

  • Idioma de escrita: Coreana
  • País de referência: Todos os países country-flag

Selecionar idioma

  • Português
  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar

Texto resumido pela IA durumis

  • A reflexão é uma API que permite acessar informações de classe no tempo de execução e manipular as classes da maneira que desejar.
  • Por meio da reflexão, você pode criar instâncias de classes e acessar seus campos e métodos, independentemente dos modificadores de acesso, sendo particularmente útil para gerenciar dependências dinamicamente em grandes desenvolvimentos como frameworks.
  • No entanto, é melhor usá-la apenas quando necessário, pois pode comprometer o encapsulamento e resultar em perda de desempenho.

O que é reflexão?

A reflexão é uma API que permite, através de um objeto de tipo Class carregado na área de heap, criar instâncias da classe desejada e acessar os campos e métodos da instância, independentemente dos modificadores de acesso.



Aqui, carregar uma classe significa que o carregador de classes do JVM concluiu o carregamento do arquivo de classe e, em seguida, criou um objeto de tipo Classcontendo informações sobre essa classe, armazenando-o na área de heap da memória. Observe que isso é diferente de um objeto criado com a palavra-chave new. Se você não entender o objeto de tipo Class, consulte a documentação do JDK para o objeto java.lang.class.


Como usar

Antes de usar a reflexão, você precisa obter um objeto de tipo Class carregado na área de heap. Existem três maneiras de fazer isso.


  • Obter de Class.class
  • Obter de Instance.getClass()
  • Obter de Class.forName("nome da classe")


public class Member {

    private String name;

    protected int age;

    public String hobby;

    public Member() {
    }

    public Member(String name, int age, String hobby) {
        this.name = name;
        this.age = age;
        this.hobby = hobby;
    }

    public void speak(String message) {
        System.out.println(message);
    }

    private void secret() {
        System.out.println("A senha é 1234.");
    }

    @Override
    public String toString() {
        return "Member{" +
            "name='" + name + '\'' +
            ", age=" + age +
            ", hobby='" + hobby + '\'' +
            '}';
    }
}

public class Main {

    public static void main(String[] args) throws ClassNotFoundException {
        Class memberClass = Member.class;
        System.out.println(System.identityHashCode(memberClass));

        Member member = new Member("Jayon", 23, "Desenvolvimento de Dara쓰");
        Class memberClass2 = member.getClass();
        System.out.println(System.identityHashCode(memberClass2));

        Class memberClass3 = Class.forName("{nome do pacote}.Member");
        System.out.println(System.identityHashCode(memberClass3));
    }
}

// Saída de execução
1740000325
1740000325

Você pode ver que as três instâncias de tipo Class obtidas pelos três métodos são todas as mesmas. Não importa qual método você use, o valor hash é o mesmo, então você pode usar o método apropriado para a situação.


Agora, você pode criar instâncias dessa classe usando o tipo Class obtido e acessar os campos e métodos da instância, independentemente dos modificadores de acesso. Primeiro, vamos criar uma instância dessa classe.


public class Main {

    public static void main(String[] args) throws Exception {
        // Imprimir todos os construtores de Member
        Member member = new Member();
        Class memberClass = member.getClass();
        Arrays.stream(memberClass.getConstructors()).forEach(System.out::println);

        // Criar instância usando o construtor padrão de Member
        Constructor constructor = memberClass.getConstructor();
        Member member2 = constructor.newInstance();
        System.out.println("member2 = " + member2);

        // Criar instância usando outro construtor de Member
        Constructor fullConstructor =
            memberClass.getConstructor(String.class, int.class, String.class);
        Member member3 = fullConstructor.newInstance("Jayon", 23, "Desenvolvimento de Dara쓰");
        System.out.println("member3 = " + member3);
    }
}

// Saída de execução
public Member()
public Member(java.lang.String,int,java.lang.String)
member2 = Member{name='null', age=0, hobby='null'}

Você pode obter um construtor usando getConstructor() e criar dinamicamente uma instância de Member usando newInstance().

Por fim, vamos acessar os campos e métodos da instância, independentemente dos modificadores de acesso.

public class Main {

    public static void main(String[] args) throws Exception {
        Member member = new Member("Jayon", 23, "Desenvolvimento de Dara쓰");
        Class memberClass = member.getClass();

        // Acesso ao campo
        Field[] fields = memberClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            System.out.println(field.get(member));
        }
        fields[0].set(member, "Jayon2");
        System.out.println(member);

        // Acesso ao método
        Method speakMethod = memberClass.getDeclaredMethod("speak", String.class);
        speakMethod.invoke(member, "Teste de reflexão");

        Method secretMethod = memberClass.getDeclaredMethod("secret");
        secretMethod.setAccessible(true);
        secretMethod.invoke(member);
    }
}

// Saída de execução
Jayon
23
Desenvolvimento de Dara쓰
Member{name='Jayon2', age=23, hobby='Desenvolvimento de Dara쓰'}
Teste de reflexão

Você pode obter todas as variáveis de instância da classe usando getDeclaredFileds(), obter o valor do campo usando get() e modificar o valor do campo usando set(). Ao fazer isso, observe que você precisa passar true para o argumento de setAccessible() ao acessar campos com modificador de acesso private.


Da mesma forma, você pode obter um método usando getDeclaredMethod(). Neste caso, você precisa passar o nome do método e o tipo de parâmetro como argumentos. Da mesma forma, você precisa definir o argumento de setAccessible() como true ao acessar métodos com modificador de acesso private. Por fim, você pode chamar o método obtido pela API de reflexão usando invoke().


Prós e contras

  • Prós
    • Oferece flexibilidade para criar instâncias de classes em tempo de execução e acessar campos e métodos, independentemente dos modificadores de acesso, para realizar as tarefas necessárias.
  • Contras
    • Viola a encapsulação.
    • As instâncias são criadas em tempo de execução, então o tipo não pode ser verificado em tempo de compilação.
    • As instâncias são criadas em tempo de execução, então é difícil entender o fluxo de trabalho específico.
    • O uso da reflexão para acessar campos e métodos é mais lento do que o acesso direto. (Não é sempre mais lento).


Razões para usar

A API de reflexão permite acessar informações sobre classes em tempo de execução e manipular classes como quiser. Mesmo campos e métodos declarados com modificadores de acesso private podem ser manipulados. Pode parecer que esta é uma técnica que não deve ser usada porque viola a encapsulação do design orientado a objetos.


No nível do console de pequeno porte, o desenvolvedor pode entender completamente os objetos e as dependências usados no programa em tempo de compilação. No entanto, em estágios de desenvolvimento de grande escala, como frameworks, é difícil entender muitos objetos e dependências. Neste caso, a reflexão pode ser usada para criar classes dinamicamente e estabelecer dependências.


Por exemplo, no Bean Factory do Spring, você pode ver que, se apenas aplicar as anotações @Controller, @Service e @Repository, o Bean Factory cria e gerencia automaticamente as classes com essas anotações anexadas. O desenvolvedor nunca disse ao Bean Factory sobre essa classe, mas isso é possível devido à reflexão. Se uma classe com essa anotação for encontrada durante a execução, ela será criada usando a reflexão, e o campo necessário será injetado e armazenado no Bean Factory.


Claro, como mencionado acima, ele viola a encapsulação, então é melhor usá-lo apenas quando necessário.


Fonte

제이온
제이온
제이온
제이온
[Effective Java] Item 1: Considere métodos de fábrica estáticos em vez de construtores Os métodos de fábrica estáticos são uma maneira flexível e eficiente de criar instâncias em vez de construtores. Eles podem ter um nome, retornar instâncias que atendem a condições específicas e melhorar o desempenho por meio do cache. Ao contrário do pad

27 de abril de 2024

[Effective Java] Item 6. Evite a criação de objetos desnecessários Este é um guia sobre como reduzir a criação de objetos desnecessários em Java. Para objetos imutáveis como String, Boolean, é melhor usar literais e, para expressões regulares, é melhor armazenar em cache a instância Pattern. Além disso, o autoboxing pode

28 de abril de 2024

[Effective Java] Item 2: Considere um construtor se você tiver muitos parâmetros Ao criar objetos com muitos parâmetros, o padrão de construtor pode tornar o código mais limpo e legível. Crie um objeto de construtor com parâmetros obrigatórios e use métodos setter para definir parâmetros opcionais e, em seguida, chame o método build()

27 de abril de 2024

[Javascript] Estrutura do Objeto (V8) O Objeto JavaScript no motor V8 é otimizado como uma estrutura dependendo do estado, alternando entre o modo Rápido e o modo Dicionário, que funciona como um mapa hash. O modo Rápido é rápido quando as chaves e valores são quase fixos, mas quando uma nova
곽경직
곽경직
곽경직
곽경직
곽경직

18 de março de 2024

Para mim, que quero dar um bom feedback Você quer aprender métodos eficazes de feedback para o crescimento de sua equipe? Este artigo enfatiza a importância do 'feedforward', que envolve a descoberta e elogio dos pontos fortes de um membro da equipe, e fornece métodos para melhorar as habilidad
울림
울림
울림
울림

18 de março de 2024

[Não graduado, sobrevivendo como desenvolvedor] 16. Dicas para criar um portfólio de desenvolvedor júnior Desenvolvedores juniores (especialmente aqueles sem formação em informática) precisam explicar claramente os serviços ou funcionalidades desenvolvidos no seu portfólio, além das tecnologias utilizadas. Por exemplo, em um projeto de "comunidade para candid
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 de abril de 2024

[Não graduado, sobrevivendo como desenvolvedor] 14. Resumo do conteúdo da entrevista técnica frequente para desenvolvedores juniores Guia de preparação para entrevista técnica para desenvolvedores juniores. Área de memória principal, estrutura de dados, RDBMS e NoSQL, orientação de procedimentos e orientação de objetos, sobreposição e sobrecarga, algoritmo de substituição de página, pr
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 de abril de 2024

Ideias para melhorar o programa de negociação automatizada Este artigo apresenta ideias para melhorar as funcionalidades do programa de negociação automatizada de Grid Trading, sugerindo a inclusão de gerenciamento de grandes eventos, lógica de gerenciamento de investimentos, funcionalidade de posição curta, entr
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마

21 de abril de 2024

[React Hook] useState Este artigo aprofunda a explicação do hook useState do React, incluindo por que ele causa o re-render da componente inteira durante o re-render, como manter o valor e a estrutura interna da implementação. Através da análise do código ReactFiberHooks.js, v
Sunrabbit
Sunrabbit
Sunrabbit
Sunrabbit

14 de março de 2024