JAVA 反射

一、 什么是反射?
二、反射能做什么?
一、 什么是反射?

用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。

如果你是一个Android Developer,前辈们都会教导你尽量少用反射,效率太低,太慢。“射”嘛,射的太快就不好了,所以反射虽然慢点,但是偶尔射一下还是很”爽”的。

二、反射能做什么?

1、新建类的实例

我们知道所有的类都继承子顶级父类Object,而Object中有hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。我们这里就需要使用的Class对象,注意C是大写,我们可以通过一下方式来获取Class对象

1.Class.forName(“类名字符串”) (注意:类名字符串必须是全称,包名+类名)

2.类名.class

3.实例对象.getClass()

在Class类中有一个非常重要的方法

public T newInstance() throws InstantiationException, IllegalAccessException {
return newInstanceImpl();
}

private native T newInstanceImpl() throws IllegalAccessException, InstantiationException;
查看Api可以看到调用newInstace方法可以返回当前class对应的实例对象。接下来看一个小的Demo

public class Reflection {

public static void main(String[] args) {

    // 普通创建类的实例

    People p1 = new People();
    System.out.println(p1.getName());
    // 利用反射获取类的实例
    Class clazz = People.class;
    // 常用方式,注意括号中需要放类的全路径名
    // Class clazz = Class.forName("reflection.People");
    // Class clazz = p1.getClass();
    try {
        People p2 = (People) clazz.newInstance();
        System.out.println(p2.getName());
    } catch (Exception e) {
        e.printStackTrace();
    }

}

}

class People {

private String name = "张三";
private int age;

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;
}

}
输入结果:

张三
张三
2、获取成员变量和方法

在讲之前我们先来看这样一个小按理,JSON数据转JavaBaen对象,在不用解析库的情况下,一般我们会这样做

private void analysisDate(JSONObject response) throws JSONException {
int announceid = response.getInt(“announceid”);
String title = response.getString(“title”);
String hits = response.getString(“hits”);
String addtime = response.getString(“addtime”);
NewsNotifyItem newsNotifyItem = new NewsNotifyItem(announceid,
title, hits, addtime);
}
}
每当我们需要解析额时候,都需要根据不同javabean来进行相应的解析,我们每次进行的操作都是一样的,只是解析的数据不同而已,结合上篇帖子讲到的泛型,这里我们就可以再利用反射来自己做一个Json解析工具。

下面是我写的一个JsonObject对象转JavaBean的一个工具类,需要注意的是,JSON的key需要和字段名保持一致,先说下思路

①首先通过反射获取JavaBean中的所有字段值的名称

②拼接出set方法

③由于字段名和Json的key值相同,利用自动名获取Json中的值并填充的实例对象中

public class Json2BeanUtils {

public static <T> T jsonToBean(JSONObject response, Class<T> clazz) {
    try {
        // 创建类的实例
        Object object = Class.forName(clazz.getName()).newInstance();
        // 获取类中的所有成员变量
        Field[] fields = object.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            //设置权限
            fields[i].setAccessible(true);
            // 获取字段的名称
            String fieldName = fields[i].getName();
            // 过滤掉UID
            if (fieldName.endsWith("serialVersionUID")) {
                continue;
            }
            // 获取字段的类型
            String fieldType = fields[i].getGenericType().toString();
            // 拼接出JavaBean中的set方法 这里有一个坑 后面讲解
            String methodName = "set"
                    + fieldName.substring(0, 1).toUpperCase()
                    + fieldName.substring(1);
            try {
                // 判断变量类型
                if (fieldType.endsWith("class java.lang.String")) {
                    // 获取到set方法
                    Method m = object.getClass().getMethod(methodName,
                            String.class);
                    String value = null;
                    try {
                        // 从JsonObj中取出相应的值
                        value = response.getString(fieldName);
                    } catch (Exception e) {
                        e.printStackTrace();
                        value = "";
                    }
                    if (TextUtils.isEmpty(value)) {
                        value = "";
                    } else if (value.endsWith("null")) {
                        value = "";
                    }
                    // 赋值
                    m.invoke(object, value);
                } else if (fieldType.endsWith("int")
                        || fieldType.endsWith("class java.lang.Integer")) {
                    // int 类型
                    System.out.println();
                    Method m = object.getClass().getMethod(methodName,
                            int.class);
                    int value = -1;
                    try {
                        value = response.getInt(fieldName);
                    } catch (Exception e) {
                        e.printStackTrace();
                        value = -1;
                    }
                    m.invoke(object, value);

                } else if (fieldType.endsWith("boolean")
                        || fieldType
                                .endsWith("fieldType:class java.lang.Boolean")) {
                    // boolean 类型
                    Method m = object.getClass().getMethod(methodName,
                            boolean.class);
                    boolean value = false;
                    try {
                        value = response.getBoolean(fieldName);
                    } catch (Exception e) {
                        e.printStackTrace();
                        value = false;
                    }
                    m.invoke(object, value);
                } else if (fieldType.endsWith("double")
                        || fieldType
                                .endsWith("fieldType:class java.lang.Double")) {
                    // double 类型
                    Method m = object.getClass().getMethod(methodName,
                            double.class);
                    double value = -1D;
                    try {
                        value = response.getDouble(fieldName);
                    } catch (Exception e) {
                        e.printStackTrace();
                        value = -1D;
                    }
                    m.invoke(object, value);
                } else if (fieldType.endsWith("char")) {
                    // char类型 JSONObject 没有char
                    Method m = object.getClass().getMethod(methodName,
                            String.class);
                    String value = "";
                    try {
                        value = response.getString(fieldName);
                    } catch (Exception e) {
                        e.printStackTrace();
                        value = "";
                    }
                    m.invoke(object, value);
                } else if (fieldType.endsWith("float")
                        || fieldType
                                .endsWith("fieldType:class java.lang.Float")) {
                    // float类型
                    Method m = object.getClass().getMethod(methodName,
                            double.class);
                    double value = -1D;
                    try {
                        value = response.getDouble(fieldName);
                    } catch (Exception e) {
                        e.printStackTrace();
                        value = -1D;
                    }
                    m.invoke(object, value);

                } else if (fieldType.endsWith("short")
                        || fieldType
                                .endsWith("fieldType:class java.lang.Short")) {
                    // short
                    Method m = object.getClass().getMethod(methodName,
                            short.class);
                    int value = -1;
                    try {
                        value = response.getInt(fieldName);
                    } catch (Exception e) {
                        e.printStackTrace();
                        value = -1;
                    }
                    m.invoke(object, value);
                } else if (fieldType.endsWith("byte")
                        || fieldType
                                .endsWith("fieldType:class java.lang.Byte")) {
                    Method m = object.getClass().getMethod(methodName,
                            byte.class);
                    int value = -1;
                    try {
                        value = response.getInt(fieldName);
                    } catch (Exception e) {
                        e.printStackTrace();
                        value = -1;
                    }
                    m.invoke(object, value);
                } else if (fieldType.endsWith("long")
                        || fieldType
                                .endsWith("fieldType:class java.lang.Long")) {
                    Method m = object.getClass().getMethod(methodName,
                            long.class);
                    Long value = -1L;
                    try {
                        value = response.getLong(fieldName);
                    } catch (Exception e) {
                        e.printStackTrace();
                        value = -1L;
                    }
                    m.invoke(object, value);
                }  
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
        return (T) object;
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

}
这里需要注意一个坑,先来看一段代码

class People {

private String name;
private int age;
private String mSex;

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 getmSex() {
    return mSex;
}
// 这里就出了问题  
public void setmSex(String mSex) {
    this.mSex = mSex;
}

}
当我们自动生成get set方法时,会将字段的首字母大写,我们在上面拼接set 方法时,也是基于这样的规则来拼装的。但是 当我们的字段名为 aAbbb 时,则生成的get set 方法则不会大写。解决方案也很简单,注意字段命名或者在拼接时对第二个自动进行大小写判断。这样我们自己写的Json解析工具就搞定, 以后每次解析只需一行代码即可OK。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值