关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »Java高级特性之反射学习总结

    Java高级特性之反射学习总结

    2016-01-11 00:00:00 出处:itjs.cn
    分享

    老规矩我们还是先提出几个问题,一门技术必然要能解决一定的问题,才有去学习掌握它的价值

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

    一、 什么是反射?

    用在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。

    今天反射就暂时讲到这里。其实反射的作用远不于此,这里只是使用了反射的冰山一角,结合注解和泛型,反射可以做的事更多,但是还是和开头讲的一样,反射用起来虽然很爽,但是不能乱射,和频繁的射,“射”的太多。“性”能会出问题!(o(∩_∩)o )。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。