Han Shunping aprendeu Java em 30 dias sem fundamento [Capítulo 18 Reflexão]

Uma necessidade provoca reflexão

Por favor, veja as seguintes perguntas:

  1. re.propertiesDe acordo com as informações especificadas no arquivo de configuração , crie um objeto e chame o método
//re.properties
classfullpath=com.Cat
method=hi

Quickstart, com.ReflectionQuestion.java

package com;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Properties;

public class ReflectionQuestion {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //根据配置文件re.properties指定的信息,创建对象并调用方法
        //传统方式 new 对象-》调用方法
        Cat cat = new Cat();
        cat.hi();

        //1、使用Properties类,可以读写配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("./18反射/re.properties"));
        String classfullpath = properties.get("classfullpath").toString();
        String method = properties.get("method").toString();
//        List method = List.of(properties.get("method").toString().split(","));
        System.out.println("classfullpath:" + classfullpath);
        System.out.println("method:" + method);

        //2、创建对象,使用反射机制
        //(1)加载类,返回Class类型的对象
        Class aClass = Class.forName(classfullpath);
        //(2)通过aClass得到加载的类com.Cat的对象实例
        Object o = aClass.newInstance();
        System.out.println(o.getClass());//运行类型
        // (3) 通过getMethod(),得到加载的类com.Cat的methodName "hi"的方法对象
        // 即,在反射中,可以把方法视为对象
        Method method1 = aClass.getMethod(method);
        //(4)通过method1 调用方法,即通过方法对象实现调用方法
        method1.invoke(o); //传统方法 对象方法(),反射机制 方法.invoke(对象)
        //多方法
//        for (int i = 0; i < method.size(); i++) {
//            Method method1 = aClass.getMethod((String) method.get(i));
//            method1.invoke(o); //传统方法 对象方法(),反射机制 方法.invoke(对象)
//
//        }

    }
}

public class Cat {
    private String name="miaomiao";
    public void hi(){
        System.out.println("hi"+name);
    }
    public void hi2(){
        System.out.println("hi2"+name);
    }
}

mecanismo de reflexão

Reflexão Java

  1. Permite que o programa obtenha informações internas de qualquer classe por meio da API de reflexão durante a execução, como variáveis ​​de membro, construtores, métodos de membro e assim por diante. E pode manipular as propriedades e métodos do objeto. A reflexão é usada tanto em padrões de projeto quanto na parte inferior da estrutura.
  2. Depois que a classe é carregada, um objeto do tipo Class é gerado no heap, existe apenas um objeto Class para uma classe e esse objeto contém as informações estruturais completas da classe. Obtenha a estrutura da classe através deste objeto. Este objeto é como um espelho através do qual a estrutura da aula pode ser vista, então a imagem é chamada de reflexão

[Falha na transferência da imagem do link externo, o site de origem pode ter um mecanismo anti-leeching, é recomendável salvar a imagem e carregá-la diretamente (img-rn5IYF8U-1661650781637) (https://secure2.wostatic.cn/static/aH8niBaDe8RxvGsgkuLAKs /image.png)]

O mecanismo de reflexão pode ser feito

  1. Determinar a classe de qualquer objeto em tempo de execução
  2. Construa um objeto de qualquer classe em tempo de execução
  3. Obtenha as variáveis ​​de membro e métodos de qualquer classe em tempo de execução
  4. Chame variáveis ​​de membro e métodos de qualquer objeto em tempo de execução
  5. Gerar proxy dinâmico

Principais classes relacionadas à reflexão, com.Reflection01.java

  1. java.lang.Class: representa uma classe e o objeto Class representa o objeto no heap depois que uma determinada classe é carregada
  2. java.lang.reflect.Method: representa o método da classe
  3. java.lang.reflect.Field: representa a variável membro da classe
  4. java.lang.reflect.Constructor: representa o construtor da classe

Essas classes, em java.lang.reflection, fornecem uma interface para reflexão

package com;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.*;
import java.util.Properties;

public class Reflection01 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Cat cat = new Cat();
        cat.hi();

        //1、使用Properties类,可以读写配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("./18反射/re.properties"));
        String classfullpath = properties.get("classfullpath").toString();
        String method = properties.get("method").toString();

        //2、创建对象,使用反射机制
        //(1)加载类,返回Class类型的对象
        Class cls = Class.forName(classfullpath);
        //(2)通过cls得到加载的类com.Cat的对象实例
        Object o = cls.newInstance();
        // (3) 通过getMethod(),得到加载的类com.Cat的methodName "hi"的方法对象
        // 即,在反射中,可以把方法视为对象
        Method method1 = cls.getMethod(method);
        //(4)通过method1 调用方法,即通过方法对象实现调用方法
        method1.invoke(o); //传统方法 对象方法(),反射机制 方法.invoke(对象)

        // java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量
        //得到name字段
        //getField不能得到私有的属性
        //Field name = cls.getField("name");
        Field age = cls.getField("age");
        System.out.println(age.get(o));

        //java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器
        Constructor constructor = cls.getConstructor();//()中指定构造器参数类型,
        System.out.println(constructor);

        Constructor constructor1 = cls.getConstructor(String.class);//传入的String.class就是String类的Class对象
        System.out.println(constructor1);
    }
}

Prós e contras do Reflection, com.Reflection02.java

  • Vantagens: Os objetos podem ser criados e usados ​​dinamicamente (também o núcleo subjacente da estrutura) Flexível de usar, sem mecanismo de reflexão, a tecnologia da estrutura deve ir para o suporte subjacente
  • Desvantagens: O uso de reflexão é basicamente uma execução interpretada, o que afeta a velocidade de execução

Otimização de chamada reflexiva - desative as verificações de acesso

  • Os objetos Método, Campo e Construtor têm métodos setAccessible()
  • A função de setAccessible é ativar e desativar a verificação de segurança de acesso
  • O valor do parâmetro é true, o que significa que o objeto refletido cancela a verificação de acesso quando é usado, melhorando a eficiência da reflexão. Um valor de parâmetro de false significa que o objeto refletido executa verificações de acesso

Classe classe, com.Class01.java

  • A classe também é uma classe, então também herda a classe Object
  • O objeto de classe Class não é novo, mas criado pelo sistema
  • Para um objeto de classe Class de uma determinada classe, há apenas uma cópia na memória, porque a classe é carregada apenas uma vez
  • Cada instância de classe lembrará de qual instância de classe foi gerada
  • Por meio de Class, a estrutura completa de uma classe pode ser obtida de forma completa, por meio de uma série de APIs
  • Objetos de classe são armazenados no heap
  • Os dados binários do bytecode da classe são colocados na área do método e, em alguns lugares, são chamados de metadados da classe (incluindo código do método, nome da variável, nome do método, direitos de acesso, etc.)
package com;
public class Class01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //Class对象不是new的,而是系统创建的
        //(1)传统new对象
//        Cat cat = new Cat();
        //(2)反射方式
        Class<?> cls1 = Class.forName("com.Cat");
        //对于某个类的Class类对象,在内存中只有一份,因为类只加载一次[演示]
        Class<?> cls2 = Class.forName("com.Cat");
        System.out.println(cls1.hashCode());//1175962212
        System.out.println(cls2.hashCode());//1175962212
    }
}

Métodos comuns de classe, com.Class02.java

package com;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class Class02 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        String classAllPath="com.Car";
        //1、获取Car类对应的Class对象
        //<?>表示不能确定的Java类型
        Class<?> cls = Class.forName(classAllPath);
        //2、输出cls
        //(1)输出cls是哪个类的cls对象
        System.out.println(cls);//class Car
        //(2)输出cls运行类型
        System.out.println(cls.getClass());//class java.lang.Class
        //3、得到包名
        System.out.println(cls.getPackage().getName());
        //4、得到类名
        System.out.println(cls.getName());
        //5、通过cls创建对象实例
        Car car = (Car) cls.newInstance();
        System.out.println(car);//Car{brand='宝马', price=100, color='白色'}
        //6、通过反射获取属性 brand,私有属性会报错
        Field brand = cls.getField("brand");
        System.out.println(brand.get(car));//宝马
        //7、通过反射给属性赋值
        brand.set(car,"奔驰");
        System.out.println(brand.get(car));//奔驰
        //8、遍历所有属性
        Field[] fields = cls.getFields();
        for (Field f :fields) {
            System.out.println(f.getName());//所有属性名称
        }
    }
}
class Car{
    public String brand="宝马";
    public int price=100;
    public String color="白色";

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                ", color='" + color + '\'' +
                '}';
    }
}

Obtenha o objeto Class, com.GetClass_.java

  1. Premissa: O nome completo da classe de uma classe é conhecido e a classe está no caminho da classe, que pode ser obtido por meio do método estático forName() da classe Class, e ClassNotFoundException pode ser lançada.

    Exemplo: Classe cls1=Class.forName(“java.lang.Cat”)

    Cenários de aplicativos: usados ​​principalmente para arquivos de configuração, leitura do caminho completo das classes e carregamento de classes

  2. Premissa: Se a classe específica for conhecida, ela pode ser obtida através de class.class Este método é o mais seguro e confiável, e o desempenho do programa é o mais alto.

    Exemplo: Classe cls2=Cat.class

    Cenário de aplicação: usado principalmente para passagem de parâmetros, como obter o objeto construtor correspondente por meio de reflexão

  3. Premissa: Uma instância de uma determinada classe é conhecida e o método getClass() da instância é chamado para obter o objeto Class

    Exemplo: Classe cls3=object.getClass();//tipo de execução

    Cenário do aplicativo: obtenha o objeto Class criando um bom objeto

  4. Outros métodos

    ClassLoader cl = 对象.getClass().getClassLoader();

    Class cls4=cl.loadClass("nome completo da classe")

  5. Dados básicos (int, chart, boolean, float, double, byte, long, short) podem ser obtidos da seguinte forma Objeto de classe

    Classe cls=tipo de dados básicos.class

  6. A classe wrapper correspondente ao tipo de dados básico, você pode obter o objeto de classe Class por meio de .type

    Classe cls=classe de embalagem.TYPE

package com;

public class GetClass_ {
    public static void main(String[] args) throws ClassNotFoundException {
        //1、Class.forName
        String classAllPath="com.Cat";
        Class<?> cls1 = Class.forName(classAllPath);
        System.out.println(cls1);
        //2、类名.class,应用场景:用于参数传递
        Class<Cat> cls2 = Cat.class;
        System.out.println(cls2);
        //3、对象.getClass(),应用场景:有对象实例
        Cat cat = new Cat();
        Class<? extends Cat> cls3 = cat.getClass();
        System.out.println(cls3);
        //4、通过类加载器来获得类的Class对象
        //(1)先得到类加载器 cat
        ClassLoader classLoader = cat.getClass().getClassLoader();
        //(2)通过类加载器得到Class对象
        Class<?> cls4 = classLoader.loadClass(classAllPath);
        System.out.println(cls4);

        //cls1\2\3\4是同一个对象
        //5、基本数据(int、chart、boolean、float、double、byte、long、short)按如下方式得到Class类对象
        Class<Integer> integerClass = int.class;
        Class<Character> characterClass = char.class;
        Class<Boolean> booleanClass = boolean.class;
        System.out.println(integerClass); //int

        //6、基本数据类型对应的包装类,可以通过.type得到Class类对象
        Class<Integer> type1 = Integer.TYPE;
        Class<Character> type2 = Character.TYPE;
        System.out.println(type1); // int

        System.out.println(integerClass.hashCode());//1769597131
        System.out.println(type1.hashCode());//1769597131
    }
}

Quais objetos possuem objetos Class, com.AllTypeClass.java

  1. Classe externa, classe interna membro, classe interna estática, classe interna local, classe interna anônima
  2. interface: interface
  3. variedade
  4. enum: enumeração
  5. anotação: anotação
  6. tipo de dados básico
  7. vazio
package com;

import java.io.Serializable;

public class AllTypeClass {
    public static void main(String[] args) {
        //1. 外部类、成员内部类、静态内部类、局部内部类、匿名内部类
        Class<String> cls1 = String.class;//外部类
        Class<Serializable> cls2 = Serializable.class;//接口
        Class<Integer[]> cls3 = Integer[].class;//数组
        Class<float[][]> cls4 = float[][].class;//二维数组
        Class<Deprecated> cls5 = Deprecated.class;//注解
        Class<Thread.State> cls6 = Thread.State.class;//枚举
        Class<Long> cls7 = long.class;//基本数据类型
        Class<Void> cls8 = void.class;//void数据类型
        Class<Class> cls9 = Class.class;//外部类
        System.out.println(cls1);//class java.lang.String
        System.out.println(cls2);//interface java.io.Serializable
        System.out.println(cls3);//class [Ljava.lang.Integer;
        System.out.println(cls4);//class [[F
        System.out.println(cls5);//interface java.lang.Deprecated
        System.out.println(cls6);//class java.lang.Thread$State
        System.out.println(cls7);//long
        System.out.println(cls8);//void
        System.out.println(cls9);//class java.lang.Class
    }
}

carregamento de classe

Instruções básicas, com.ClassLoad_java.java

O mecanismo de reflexão é a chave para o Java realizar a linguagem dinâmica, ou seja, realizar o carregamento dinâmico das classes por meio da reflexão

  • Carregamento estático: carrega classes relacionadas em tempo de compilação, caso contrário, um erro será relatado, a dependência é muito forte
  • Carregamento dinâmico: carrega a classe necessária em tempo de execução, se a classe não for usada em tempo de execução, nenhum erro será relatado mesmo que a classe não exista, reduzindo a dependência
package com;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;

public class ClassLoad_ {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入key");
        String key = scanner.next();
        switch (key){
            case "1":
                //静态加载必须编写Notexist类
//                Notexist no = new Notexist();//静态加载
//                no.hi();
                break;
            case "2":
                //反射:动态加载
                //动态加载不编写Notexist类也不会报错,只有当动态加载该类时才会报错
                Class<?> cls = Class.forName("Notexist");
                Object o = cls.newInstance();
                Method m = cls.getMethod("nohi");
                m.invoke(o);
                break;
        }
    }
}

tempo de carregamento da aula

  1. Quando um objeto é criado (novo)
  2. quando a subclasse é carregada
  3. Ao chamar um membro estático em uma classe
  4. por reflexão

processo de carregamento de classe

[Falha na transferência da imagem do link externo, o site de origem pode ter um mecanismo de link anti-roubo, é recomendável salvar a imagem e carregá-la diretamente (img-1vp9ldPJ-1661650781638)(https://secure2.wostatic.cn/static/ 2ZQzprDgKiqZ8VHian3ZFu/image.png)]

1. Etapa de carregamento

O principal objetivo da JVM neste estágio é converter bytecode de diferentes fontes de dados (talvez arquivos de classe, pacotes jar ou até mesmo a rede) em fluxos de bytes binários e carregá-los na memória e gerar uma representação da classe.java. objeto lang.Class

Em segundo lugar, a fase de conexão - verificação

  1. O objetivo é garantir que as informações contidas no fluxo de bytes do arquivo Class atendam aos requisitos da máquina virtual atual e não coloquem em risco a segurança da própria máquina virtual
  2. Inclui: validação de formato de arquivo, validação de metadados, validação de bytecode e validação de referência real
  3. Você pode considerar o uso do parâmetro -Xverify:none para desativar a maioria das medidas de verificação de classe e diminuir o tempo de carregamento da classe da máquina virtual

2. Etapa de conexão - preparação

  1. A JVM alocará memória e inicializará variáveis ​​estáticas neste estágio (correspondente ao valor inicial padrão do tipo de dados, como 0, nulo, falso, etc.). A memória usada por essas variáveis ​​será alocada na área de método

Em segundo lugar, a fase de conexão - análise

  1. A máquina virtual substitui as referências simbólicas no pool constante por referências diretas

3. Fase de inicialização

  1. No estágio de inicialização, o código do programa Java definido na classe é realmente executado. Este estágio é o processo de execução do método ()
  2. O método () é usado pelo compilador para coletar automaticamente as ações de atribuição de todas as variáveis ​​estáticas na classe e as instruções no bloco de código estático em sequência de acordo com a ordem em que as instruções aparecem no arquivo de origem e mesclá-las
  3. A máquina virtual garante que o método () de uma classe esteja corretamente bloqueado e sincronizado em vários threads. Se vários threads inicializarem uma classe ao mesmo tempo, apenas um thread executará o método () desta classe. Todos os outros threads precisam bloqueie e espere até que a thread ativa execute o método ()

Obtendo informações da estrutura de classe por meio de reflexão

O primeiro grupo: class java.lang.Class, com.ReflectionUtils.java

  1. getName: Obtém o nome completo da classe
  2. getSimpleName: Obtém o nome da classe simples
  3. getFields: obtém todos os atributos públicos modificados, incluindo esta classe e a classe pai
  4. getDeclaredFields: Obtenha todos os atributos desta classe
  5. getMethods: obtém todos os métodos públicos modificados, incluindo esta classe e a classe pai
  6. getDeclaredMethods: Obtenha todos os métodos desta classe
  7. getConstructors: Obtenha todos os construtores públicos modificados nesta classe
  8. getDeclaredConstructors Obter todos os construtores desta classe
  9. getPackage: retorna as informações do pacote na forma de Package
  10. getSuperClass: Retorna as informações da classe pai na forma de Classe
  11. getlinterfaces: retorna informações da interface na forma de Class[
  12. getAnnotations: retorna informações de anotação na forma de Anotação
package com;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;

public class ReflectionUtils {
    public static void main(String[] args) {

    }
    //第一组方法API
    @Test
    public void api_01() throws ClassNotFoundException {
        //得到Class对象
        Class<?> personCls = Class.forName("com.Person");
        //1. getName:获取全类名
        System.out.println(personCls.getName());
        //2. getSimpleName:获取简单类名
        System.out.println(personCls.getSimpleName());
        //3. getFields:获取所有public修饰的属性,包含本类以及父类的
        Field[] fields = personCls.getFields();
        for (Field field : fields) {
            System.out.println("本类及父类的属性:"+field.getName());
        }
        //4. getDeclaredFields:获取本类中所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("获取本类中所有属性:"+declaredField);
        }
        //5. getMethods:获取所有public修饰的方法,包含本类以及父类的
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println("本类以及父类的"+method);
        }
        //6. getDeclaredMethods:获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类中所有方法"+declaredMethod);
        }
        //7. getConstructors:获取所有public修饰的构造器,包含本类以及父类的构造器
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("本类以及父类的构造器"+constructor);
        }
        //8. getDeclaredConstructors获取本类中所有构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("本类中所有构造器"+declaredConstructor);
        }
        //9. getPackage:以Package形式返回包信息
        System.out.println(personCls.getPackage());
        //10. getSuperClass:以Class形式返回父类信息
        Class<?> superclass = personCls.getSuperclass();
        System.out.println("返回父类的class对象:"+superclass);
        //11. getlnterfaces:以Class[形式返回接口信息
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println("接口信息"+anInterface);
        }
        //12. getAnnotations:以Annotation形式返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("返回注解信息"+annotation);
        }
    }
}
class A{
    public String hobby;
    public A() {}
    public void hi(){}
}
interface IA{}
interface IB{}
@Deprecated
class Person extends A implements IA,IB{
    //属性
    public String name;
    protected int age;
    String job;
    private double sal;
    //构造函数
    public Person(String name) {
        this.name = name;
    }
    private Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //方法
    public void m1(){}
    protected void m2(){}
    void m3(){}
    private void m4(){}
}

O segundo grupo: classe java.lang.reflect.Field

  1. getModifiers: retorna os modificadores como um int

    O modificador padrão é 0, public é 1, private é 2, protect é 4, static é 8 e final é 16. Se for public static, é 1+8=9

  2. getType: retorna o tipo na forma de Classe

  3. getName: retorna o nome do atributo

O terceiro grupo: classe java.lang.reflect.Method

  1. getModifiers: retorna modificadores na forma de int
    [Nota: o modificador padrão é o, public é 1, private é 2, protected é 4, static é 8, final é 16]
  2. getReturnType: Obtém o tipo de retorno na forma de Classe
  3. getName: retorna o nome do método
  4. getParameterTypes: Retorna um array de tipos de parâmetros na Classe

O quarto grupo: classe java.lang.reflect.Constructor

  1. getModifiers: retorna os modificadores como um int
  2. getName: retorna o nome do construtor (nome completo da classe)
  3. getParameterTypes: para Class[retorna matriz de tipo de parâmetro]

Crie objetos por meio de reflexão, com.ReflectCreateInstance.java

  1. Método 1: Chame o construtor público sem argumentos modificado na classe

  2. Método 2: chamar o construtor especificado na classe

  3. Métodos relacionados à classe

    newInstance: Chame o construtor sem argumentos na classe para obter o objeto da classe correspondente

    getConstructor(Class cls): Obtém o objeto construtor público correspondente de acordo com a lista de parâmetros

    getDecalaredConstructor(Class cls): Obtenha todos os objetos construtores correspondentes de acordo com a lista de parâmetros

  4. Métodos relacionados à classe do construtor

    setAccessible: força bruta, construtores privados podem ser acessados ​​usando reflexão

    newInstance(Object obj): chama o construtor

package com;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectCreateInstance {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //通过反射创建某类的对象,要求该类中必须有public的无参构造器
        //1、先获取User类的Class对象
        Class<?> userClass = Class.forName("com.User");
        //2、通过public的无参构造器创建实例
        Object o = userClass.newInstance();
        System.out.println(o);
        //3、通过public的有参构造器创建实例
        //constructor就是
        // public User(String name) {//public有参构造器
        //        this.name = name;}
        Constructor<?> constructor = userClass.getConstructor(String.class);
        Object zhangsan = constructor.newInstance("zhangsan");
        System.out.println(zhangsan);
        //4、通过非private的构造器创建实例
        Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
        constructor1.setAccessible(true);//暴破,使用反射可以访问private构造器
        Object lisi = constructor1.newInstance(18, "lisi");
        System.out.println(lisi);
    }
}
class User {
    private int age;
    private String name;
    public User() {}
    public User(String name) {//public有参构造器
        this.name = name;
    }
    private User(int age, String name) {
        this.age = age;
        this.name = name;
    }
    @Override
    public String toString() {
        return "User{" + "age=" + age + ", name='" + name + '\'' + '}';
    }
}

Acesse os membros da classe por meio de reflexão, com.ReflectAccessProperty.java

  1. Obtenha o objeto Field de acordo com o nome do atributo

    Campo f=cls object.getDeclaredField(nome da propriedade);

  2. 暴破:f.setAccessible(true);

  3. acesso:

    f.set(o, valor);

    syso(f.get(o));

  4. Se for uma propriedade estática, o o em set e get pode ser escrito como null

package com;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class ReflectAccessProperty {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //通过反射创建某类的对象,要求该类中必须有public的无参构造器
        //1、先获取Student类的Class对象
        Class<?> stuclass = Class.forName("com.Student");
        //2、创建对象
        Object o = stuclass.newInstance();
        System.out.println(o.getClass());//运行类型是Student
        //3.使用反射得到age属性对象
        Field age = stuclass.getField("age");
        age.set(o,88);//通过反射来操作属性
        System.out.println(age.get(o));
        //4、使用反射操作name属性 private static
        Field name = stuclass.getDeclaredField("name");
        name.setAccessible(true);
//        name.set(o,"zhangsan");
        name.set(null,"zhangsan");//name是static,因此 o 也可以写成null
        System.out.println(name.get(o));
        System.out.println(name.get(null));//获取属性值,要求name是静态的
    }
}

class Student {
    public int age;
    private static String name;
    public Student() {}
    @Override
    public String toString() {
        return "Student{" +"age=" + age +'}';
    }
}

Acessar métodos em classes por meio de reflexão, com.ReflectAccessMethod.java

  1. Obtenha o objeto do método Method de acordo com o nome do método e a lista de parâmetros:

    Método m=cls.getDeclaredMethod(nome do método,xx.class);

  2. Obter objeto: Object o=cls.newInstance();

  3. Explosão: m.setAccessible(true);

  4. Acesso: Object returnValue = m.invoke(o, lista de parâmetros atual);

  5. Nota: Se for um método estático, o parâmetro o de invocar pode ser escrito como null

package com;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //1、得到Boss类对应Class对象
        Class<?> bossCls = Class.forName("com.Boss");
        //2、创建对象
        Object o = bossCls.newInstance();
        //3.1、调用public的方法
        Method hi = bossCls.getMethod("hi", String.class);
        //3.2、调用
        hi.invoke(o, "nihao");
        //4、调用private static 方法
        Method say = bossCls.getDeclaredMethod("say",int.class,String.class,char.class);
        say.setAccessible(true);
//        System.out.println(say.invoke(o,100,"zhangsan","男"));
        System.out.println(say.invoke(null,100,"zhangsan","男"));
        //5、在反射中,如果方法有返回值,返回Object,
        // 但是运行类型和方法定义返回类型一致
        Object invoke = say.invoke(null, 300, "王武", "男");
        System.out.println(invoke.getClass());//String
    }
}

class Boss {
    public int age;
    private static String name;
    public Boss() {}
    public void hi(String s) {
        System.out.println(s);
    }
    private static String say(int n, String s, char c) {
        return n + " " + s + " " + c;
    }
}

Guess you like

Origin blog.csdn.net/weixin_65656674/article/details/126566539