java反射基础

1. 第一步的核心是获取Class

常规情况下,一个class的二进制文件唯一对应jvm中的一个class对象,class的加载大部分情况都是jvm自动处理,对于动态加载的情况,一种是通过Class.forName,另一种是通过ClassLoader.loadClass(),这两种方式都可以加载classpath下的class二进制文件,关于classpath的获取

How to print out the current project classpath

Find where java class is loaded from

 

ClassLoader.loadClass()的优势是可以自定义ClassLoader,以实现自定义class二进制字节码的加载地址,比如实现加载网络上的class二进制文件。

 

以下方式都会返回Class的实例

Class.forName()

ClassLoader.loadClass()

ClassName.class

objectName.getClass()

 

2. 获取class简要信息

void checkClass(String className) throws ClassNotFoundException {
    Class bclass = Class.forName(className);
    System.out.println("class name: " + bclass.getSimpleName());
    System.out.println();

    int modifier = bclass.getModifiers();
    System.out.println("is class public: " + Modifier.isPublic(modifier));
    System.out.println();

    Package pac = bclass.getPackage();
    System.out.println("package name: " + pac.getName());
    System.out.println();

    Class sclass = bclass.getSuperclass();
    System.out.println("super class: " + sclass.getName());
    System.out.println();

    Class[] inters = bclass.getInterfaces();
    System.out.println("implemented interface: ");
    for (Class cls : inters)
        System.out.println("\t" + cls.getName());
    System.out.println();

    Constructor[] constructors = bclass.getConstructors();
    System.out.println("constructors:");
    for (Constructor c : constructors) {
        System.out.println("\t" + c.getName());

        for (Class cls : c.getParameterTypes())
            System.out.println("\t\tparam type: " + cls.getName());
    }
    System.out.println();

    System.out.println("own methods:");
    for (Method mth : bclass.getDeclaredMethods()) {
        System.out.println("\t" + mth.getName());

        for (Class cls : mth.getParameterTypes())
            System.out.println("\t\tparam types: " + cls.getName());

        System.out.println("\t\treturn types: " + mth.getReturnType().getName());
    }
    System.out.println();

    System.out.println("fields:");
    for (Field f : bclass.getFields()) {
        System.out.print("\t" + f.getName());
        System.out.println("\t:" + f.getType().getName());
    }
}

 refer Java Reflection

 

3. 通过反射的方式查看Object里面的变量

1) getFields可以获取所有的public类型成员变量,包含所有父类的public变量

2) getDeclaredFields可以获取当前类的所有成员变量,包含private类型,但是不包含父类

以下通过循环的方式获取所有成员变量的信息

static Map<String, Object> objectToMap(Object object) {
    Map<String, Object> map = new HashMap<>();

    Class cls = object.getClass();
    while (cls != null) {
        System.out.println(cls.getName());

        for (Field field : cls.getDeclaredFields()) {
            field.setAccessible(true);

            Object value = null;
            try {
                value = field.get(object);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            System.out.println(field.getName() + " # " + value);
            if (value != null)
                map.put(field.getName(), value);
        }

        cls = cls.getSuperclass();

        System.out.println("=====================");
    }

    return map;
}

 

 

4. 通过反射的方式创建一个新的对象

假设有一个class

public class MyObject {
    private int code;
    private String msg;

    public MyObject(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

1) MyObject可能会有子类,所有的子类都会有(int, String)这样的构造函数,那么所有的子类都可以通过如下的方式创建

public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
    MyObject object = newInstance(MyObject.class, 1, "succ");
    System.out.println(object.getCode() + " # " + object.getMsg());
}

static MyObject newInstance(Class<? extends MyObject> classType, int code, String msg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    Constructor<? extends MyObject> constructor = classType.getConstructor(int.class, String.class);
    return constructor.newInstance(code, msg);
}

 

2) 通过Class的newInstance()方式创建一个对象,前提是该Class有默认构造函数或无参构造函数

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值