java进阶 -- 反射

反射

  • 类加载和类加载器
    类加载:java文件会首先被编译成class文件,class文件被jvm加载进内存并初始化数据就叫做类加载。
    类加载器:类加载器就是jvm中的一个程序,负责加载class等文件进内存。加载我们程序中的类进内存的类加载器是AppClassLoader

  • 反射的概念
    class文件加载进内存之后会产生一个Class对象,反射就是要求我们通过Class对象操作类的成员变量、构造方法、成员方法。

  • 反射的实现思路

    第一步:获取Class对象(有三种方式)

    1. 通过类名.class获取: Class c=Student.class;

    2. 通过对象.getClass(); Class c=student.getClass();

    3. 使用Class的静态forName()方法获取; Class<?> c=Class.forName(“包名.类名”);

      总结:一个类只有一个Class对象,任何方式得到的Class对象都是同一个。
      补充:通过Class对象的newInstance方法也可以创建出这个类的对象。默认执行的是public修饰的空参构造

第二步:通过Class对象获取构造方法对象、成员变量对象、成员方法对象(都有4个方法)
规律:方法带s表示获取多个对象,不带s表示获取指定的一个对象。带Declared获取任意修饰符修饰的对象,不带Declared表示只能获取
public修饰的对象。
获取构造方法对象:
Constructor<?>[] getConstructors():返回所有public修饰的构造方法对象的数组
Constructor<?>[] getDeclaredConstructors()返回所有任意修饰符修饰的构造方法对象的数组
Constructor getConstructor(Class<?>... parameterTypes):返回单个public修饰的构造方法对象,该方法的参数是构造方法中参数的Class对象,例如:String.class,int.class
Constructor getDeclaredConstructor(Class<?>... parameterTypes):返回单个任意修饰符修饰的构造方法对象
获取成员变量对象:
Field[] getFields():返回所有public修饰的成员变量对象的数组
Field[] getDeclaredFields():返回所有任意修饰符修饰的成员变量对象的数组
Field getField(String name):返回单个public修饰的成员变量对象,参数是成员变量的名称
Field getDeclaredField(String name):返回单个任意修饰符修饰的成员变量对象,参数是成员变量的名称

获取成员方法对象:
Method[] getMethods():返回所有的public修饰的成员方法对象的数组,包括继承的。
Method[] getDeclaredMethods()//返回所有任意修饰符修饰的成员方法对象的数组,不包括继承的。
Method getMethod​(String name, Class<?>... parameterTypes)//根据方法名称和参数类型或者单个public修饰的成员方法对象
Method getDeclaredMethod(String name,Class<?>... parameterTypes):根据方法名称和参数类型或者单个任意修饰符修饰的成员方法对象

第三步:操作构造方法对象、成员变量对象、成员方法对象。
操纵构造方法对象:创建对象
T newInstance​(Object... initargs) :创建一个类的对象,参数是构造方法需要的值
注意:如果构造方法是非public修饰的,那么在实例化对象之前需要使用setAccessible(true)取消检查,也叫暴力访问。
操作成员变量对象:
void set​(Object obj, Object value):给obj对象的Field成本变量设置值为value
Object get​(Object obj):获取Obj对象的Field成员变量的值并返回。
注意:如果成员变量是非public修饰的,那么在调用set/get方法之前需要使用setAccessible(true)取消检查,也叫暴力访问。
操作成员方法对象:调用方法
Object invoke​(Object obj, Object... args):调用obj对象的method对应的方法,传递的参数是args,返回值是Object类型。
注意:如果成员方法是非public修饰的,那么在调用invoke方法之前需要使用setAccessible(true)取消检查,也叫暴力访问。
反射实现思路总结

案例

实现将map集合中的数据封装到标准java类对应的属性身上

package com.jxufe_ldl.homework_01.test02;


import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

// 通过反射java类Field和Method方式完成数据封装
public class Test {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        // 定义Map集合,并给Map集合添加元素
        Map<String, Object> map=new HashMap<String, Object>();
        map.put("name","zhangsan");
        map.put("age",18);
        map.put("sex","男");

        // 调用populate()方法
        Person p = new Person();
        mypopulate(p, map);

        System.out.println(p);
    }

    // 实现将map集合中的数据封装到标准java类对应的属性身上
    public static  <E,T> void mypopulate(Object obj, Map<E,T> map) throws NoSuchMethodException, InvocationTargetException,
            IllegalAccessException {
        // 获取对象的 Class 对象
        Class<?> c = obj.getClass();

        // 获取对象的 成员变量 和 成员set方法
        Field[] fields = c.getDeclaredFields();
        Method[] methods = c.getDeclaredMethods();

        Set<E> keySet = map.keySet();
        for (E key : keySet) {
            for (Field field : fields) {
                T value = map.get(key);
//                String key1 = String.valueOf(key);
//                String field1 = String.valueOf(field);
                String str = String.valueOf(field.getName());
                if (str.equals(key)) {
                    // 获取对应的成员方法
                    // str.substring(0, 1).toUpperCase()+str.substring(1);
                    Method setField = c.getDeclaredMethod("set"+ str.substring(0, 1).toUpperCase()+str.substring(1),
                            value instanceof String ? String.class : int.class);
                    setField.setAccessible(true);

                    // 调用成员方法
                    setField.invoke(obj, value);
                }
            }
        }
        // 调用成员变量对应set方法给对象赋值
    }

   /* public static void mypopulate(Object obj, Map map) throws NoSuchMethodException, InvocationTargetException,
            IllegalAccessException {
        // 获取对象的 Class 对象
        Class<?> c = obj.getClass();

        // 获取对象的 成员变量 和 成员set方法
        Field[] fields = c.getDeclaredFields();
        Method[] methods = c.getDeclaredMethods();

        Set keySet = map.keySet();

        for (Object key : keySet) {
            Object value = map.get(key);
            String filedmeth = "set" + key;
            for (Method method : methods) {
                if (method.getName().equalsIgnoreCase(filedmeth)) {
                    method.invoke(obj, value);
            }
        }
    }
        // 调用成员变量对应set方法给对象赋值
    }*/

    /*public static void mypopulate(Object obj, Map map) throws NoSuchMethodException, InvocationTargetException,
            IllegalAccessException {
        // 获取对象的 Class 对象
        Class<?> c = obj.getClass();

        // 获取对象的 成员变量 和 成员set方法
        Field[] fields = c.getDeclaredFields();
        Method[] methods = c.getDeclaredMethods();

        // 通过对象.成员变量 = 值
        Set keySet = map.keySet();
        for (Field field : fields) {
            String fieldName = field.getName();
            for (Object key : keySet) {
                Object value = map.get(key);
                if (fieldName.equals(key)) {
                    field.setAccessible(true);
                    field.set(obj, value);
                }
            }
        }
    }*/
}

package com.jxufe_ldl.homework_01.test02;

public class Person {
    private String name;
    private int age;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值