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。
今天反射就暂时讲到这里。其实反射的作用远不于此,这里只是使用了反射的冰山一角,结合注解和泛型,反射可以做的事更多,但是还是和开头讲的一样,反射用起来虽然很爽,但是不能乱射,和频繁的射,“射”的太多。“性”能会出问题!(o(∩_∩)o )。
Java高级特性之反射学习总结的更多相关文章
- Java高级特性之反射
老规矩我们还是先提出几个问题,一门技术必然要能解决一定的问题,才有去学习掌握它的价值 一. 什么是反射? 二.反射能做什么? 一. 什么是反射? 用在Java身上指的是我们可以于运行时加载.探知.使用 ...
- Java高级特性之枚举学习总结
在Java SE5之前,我们要使用枚举类型时,通常会使用static final 定义一组int常量来标识,代码如下 public static final int MAN = 0; public s ...
- Java高级特性——反射机制(第二篇)
在Java高级特性——反射机制(第一篇)中,写了很多反射的实例,可能对于Class的了解还是有点迷糊,那么我们试着从内存角度去分析一下. Java内存 从上图可以看出,Java将内存分为堆.栈.方法区 ...
- java高级特性增强
第4天 java高级特性增强 今天内容安排: 1.掌握多线程 2.掌握并发包下的队列 3.了解JMS 4.掌握JVM技术 5.掌握反射和动态代理 java多线程增强 .1. java多线程基本知识 . ...
- paip。java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型
paip.java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http ...
- Java高级特性-String、StringBuffer和StringBuilder
Java高级特性-String.StringBuffer和StringBuilder String Java语言中的字符串值都属于String类,虽然有其他方法表示字符串(如字符串数组),但Java一 ...
- Java高级特性1_流库_初体验
Java高级特性流库_初体验 面对结果编程 在编程里, 有两种编程方式, 一种是面对过程编程, 一种是面对结果编程. 两者区别如下 面向过程编程 面向过程编程需要编程程序让程序依次执行得到自己想要的结 ...
- Java高级语法之反射
Java高级语法之反射 什么是反射 java.lang包提供java语言程序设计的基础类,在lang包下存在一个子包:reflect,与反射相关的APIs均在此处: 官方对reflect包的介绍如下: ...
- Java高级特性 第5节 序列化和、反射机制
一.序列化 1.序列化概述 在实际开发中,经常需要将对象的信息保存到磁盘中便于检索,但通过前面输入输出流的方法逐一对对象的属性信息进行操作,很繁琐并容易出错,而序列化提供了轻松解决这个问题的快捷方法. ...
随机推荐
- My.Ioc 代码示例——如何使用默认构造参数,以及如何覆盖默认构造参数
在 Ioc 世界中,有些框架(例如 Autofac/NInject/Unity)支持传递默认参数,有些框架(例如 SimpleInjector/LightInjector 等)则不支持.作为 My.I ...
- 关于svn获取获取文件时 Unable to connect to a repository at URL"https://..."执行上下文错误:参数错误
错误提示: 下面的六种解决方案都未能解决: 1.不提示输入用户名和密码,不管重装多少次都一样. 2.TortoiseSVN的setting->Saved Data->Authenticat ...
- linux list all users.
cat /etc/passwd sample of list users in linux. ref: Linux Command: List All Users In The System
- model 和 view 实现思考
采用model.view = view 和 view.model=model 进行双向绑定,还有一种方案是采用id号进行绑定,viewmodel的views 和 models 属性存放所有的id 映 ...
- C++学习之DLL注入
#include<stdio.h> #include<Windows.h> #include<TlHelp32.h> //typedef unsigned long ...
- 【USACO 2.3.5】控制公司
[题目描述] 有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分.例如,福特公司拥有马自达公司12%的股票.据说,如果至少满足了以下三个条件之一,公司A就可以控制公司B了: 公司 ...
- Python自动化运维之20、HTML
一.HTML相关概念 HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这 ...
- Python自动化运维之12、面向对象进阶
上一篇<面向对象基础>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公 ...
- codevs 1709 钉子和小球
1709 钉子和小球 1999年NOI全国竞赛 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 查看运行结果题目描述 Description有一个三角形木板 ...
- Python读取Excel数据
今天一同学给我发来一个Excel文件,让我帮他找一些信息,打开一开 8000多条数据.自己手工处理是不可能完成的的啦.作为一名程序员,当然要用程序来处理.处理生活中的问题当然是Python最为方便啦. ...