Java中的反射

目录

介绍

获取字节码的三种方式

Class类方法

反射/反编译一个类的属性(Filed)

Field类方法

通过反射机制对一个对象的属性赋值

反射/反编译一个类的方法(method)

Method类方法

通过反射机制调用一个对象的方法

反射/反编译一个类的构造方法

Constructor类方法

通过反射机制调用一个对象的构造方法

获取一个类的父类以及实现的接口


介绍

反射机制是什么

Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

我们编译时知道类或对象的具体信息,此时直接对类和对象进行操作即可,无需使用反射(reflection)

如果编译不知道类或对象的具体信息,此时应该如何做呢?这时就要用到 反射 来实现。比如类的名称放在XML文件中,属性和属性值放在XML文件中,需要在运行时读取XML文件,动态获取类的信息

编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息

比如:log4j,Servlet、SSM框架技术都用到了反射机制

获取字节码的三种方式

1.Class.forName(“完整类名带包名”)

2.对象.getClass()

3.任何类型.class

Class类方法

方法名备注
public T newInstance()创建对象
public String getName()返回完整类名带包名
public String getSimpleName()返回类名
public Field[] getFields()返回类中public修饰的属性
public Field[] getDeclaredFields()返回类中所有的属性
public Field getDeclaredField(String name)根据属性名name获取指定的属性
public native int getModifiers()获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】
public Method[] getDeclaredMethods()返回类中所有的实例方法
public Method getDeclaredMethod(String name, Class<?>… parameterTypes)根据方法名name和方法形参获取指定方法
public Constructor<?>[] getDeclaredConstructors()返回类中所有的构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)返回Class对象的无参构造方法
public Constructor getDeclaredConstructor(Class<?>… parameterTypes)根据方法形参获取指定的构造方法
public native Class<? super T> getSuperclass()返回调用类的父类
public Class<?>[] getInterfaces()返回调用类实现的接口集合

反射/反编译一个类的属性(Filed)

Field类方法
方法名介绍
public String getName()返回属性名
public int getModifiers()获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】
public Class<?> getType()以Class类型,返回属性类型【一般配合Class类的getSimpleName()方法使用】
public void set(Object obj, Object value)设置属性值
public Object get(Object obj)读取属性值

目录结构

User类

public class User {
​
    private String name;
    private String password;
    private Integer age;
    public int no;
    public String phone;
    
    public boolean login(String name,String password){
        return "zhangsan".equals(name) && "123".equals(password);
    }
​
    /**
        有参构造、无参构造、get方法、set方法、toString方法
    **/
}
通过反射机制对一个对象的属性赋值

对于public修饰的属性

/**
给属性赋值三要素
eg. 给use对象的phone属性赋值111111111111
​
要素1:对象 user
要素2:phone 属性
要素3:111111111111 值
​
读属性值两个要素
eg. 获取user对象的phone属性的值
​
要素1:对象 user
要素2:phone属性
​
**/
​
public static void reflectFiled() throws Exception {
        Class<?> userClass = Class.forName("entity.User");
        Object user = userClass.newInstance();
        Field phone = userClass.getDeclaredField("phone");
        //对象的属性.set(对象,对象的值)
        phone.set(user,"111111111111");
        //对象的属性.get(对象)
        System.out.println(phone. Get(user));
    }

对于非public修饰的属性

public static void reflectFiled() throws Exception {
        Class<?> userClass = Class.forName("entity.User");
        Object user = userClass.newInstance();
        Field name = userClass.getDeclaredField("name");
        //打破封装,让set方法可以访问非公有属性
        name.setAccessible(true);
        name.set(user,"张三");
        System.out.println(name. Get(user));
    }

结果:

反射/反编译一个类的方法(method)

Method类方法
方法名备注
public String getName()返回方法名
public int getModifiers()获取方法的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】
public Class<?> getReturnType()以Class类型,返回方法类型【一般配合Class类的getSimpleName()方法使用】
public Class<?>[] getParameterTypes()返回方法的修饰符列表(一个方法的参数可能会有多个。)【结果集一般配合Class类的getSimpleName()方法使用】
public Object invoke(Object obj, Object… args)调用方法

通过反射机制调用一个对象的方法
public static void reflectMethod() throws Exception {
        Class<?> userClass = Class.forName("entity.User");
        Object user = userClass.newInstance();
        //getDeclaredMethod(方法名,形参类型,形参类型....)
        Method login = userClass.getDeclaredMethod("login", String.class,String.class);
        //invoke(对象,形参,形参)
        //如果是非公有方法
        //login.setAccessible(true);
        Object invoke = login.invoke(user, "张三", "123");
        System.out.println(invoke);
    }

结果:

反射/反编译一个类的构造方法

Constructor类方法
方法名备注
public String getName()返回构造方法名
public int getModifiers()获取构造方法的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】
public Class<?>[] getParameterTypes()返回构造方法的修饰符列表(一个方法的参数可能会有多个。)【结果集一般配合Class类的getSimpleName()方法使用】
public T newInstance(Object … initargs)创建对象【参数为创建对象的数据】

通过反射机制调用一个对象的构造方法
public static void reflectConstructor() throws Exception {
        Class<?> userClass = Class.forName("entity.User");
        //获取这个对象的有参构造器
        Constructor<?> c1 = userClass.getDeclaredConstructor(String.class, String.class, Integer.class, int.class, String.class);
        //调用构造方法创建对象
        Object instance1 = c1.newInstance("张三", "123", 19, 111, "121212121");
        System.out.println(instance1);
​
        //获取这个对象的有参构造器
        Constructor<?> c2 = userClass.getDeclaredConstructor();
        //调用无参方法创建对象
        Object instance2 = c2.newInstance();
        System.out.println(instance2);
    }

结果:

获取一个类的父类以及实现的接口

准备

public class T extends T4 implements T1,T2,T3{
}
​
public interface T1 {
}
public interface T1 {
}
public interface T3 {
}
public class T4 {
}

代码实现:

public static void reflectSuperAndInterface() throws Exception {
        Class<?> tClass = Class.forName("entity.T");
        //获取 T 的 父类
        Class<?> superclass = tClass.getSuperclass();
        System.out.println("T的父类:"+superclass.getName());
        //获取 T 类实现的所有接口
        Class<?>[] interfaces = tClass.getInterfaces();
        System.out.println("T实现的接口如下:");
        for (Class<?> i : interfaces) {
            System.out.println(i.getName());
        }
    }

结果:

  • 37
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值