java反射快速入门(二)
上一遍博文 , 简单介绍java 反射的常用接口,本遍博文, 我会结合项目开发的实际例子讲解下 java反射的使用
现在有个需求, 要将一个对象转换成xml格式, 或者将一串xml转换一个对象, 这时我们循序渐进, 先从最简单的入手
一: 方案①
场景 : NBA球员信息描述, 实体类如下
package test.reflect2;import org.dom4j.Element;
public class UserXMLDO {
private Long id;
private String name;
private String password;
private Double height;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
}
现在要把传进来的一个userXMLDO对象转成一串xml
public static String toStringXML(UserXMLDO userXMLDO) throws Exception {
StringBuffer sb = new StringBuffer();
sb.append("<UserInfo>");
sb.append(genNodeXmlString("id", userXMLDO.getId()));
sb.append(genNodeXmlString("name", userXMLDO.getName()));
sb.append(genNodeXmlString("password", userXMLDO.getPassword()));
sb.append(genNodeXmlString("height", userXMLDO.getHeight()));
sb.append("</UserInfo>");
return sb.toString();
}
private static String genNodeXmlString(String nodeName, Object value) {
StringBuffer sb = new StringBuffer();
sb.append("<");
sb.append(nodeName);
sb.append(">");
sb.append(value);
sb.append("</");
sb.append(nodeName);
sb.append(">");
return sb.toString();
}
再提供一个方法,将xml转成userXMLDO对象
public static UserXMLDO toUserXMLDO(String xml) throws Exception {
UserXMLDO userXMLDO = new UserXMLDO();
Element rootElement = DocumentXmlHelper.read(xml).getRootElement();
for(Iterator<?> it = rootElement.elementIterator("id"); it.hasNext();) {
Element element = (Element) it.next();
userXMLDO.setId(Long.valueOf(element.getText()));
}
for(Iterator<?> it = rootElement.elementIterator("name"); it.hasNext();) {
Element element = (Element) it.next();
userXMLDO.setName(element.getText());
}
for(Iterator<?> it = rootElement.elementIterator("password"); it.hasNext();) {
Element element = (Element) it.next();
userXMLDO.setPassword(element.getText());
}
for(Iterator<?> it = rootElement.elementIterator("height"); it.hasNext();) {
Element element = (Element) it.next();
userXMLDO.setHeight(Double.valueOf(element.getText()));
}
return userXMLDO;
}
上面的方案一,是最容易的想法做法,但此做法显得有点简单粗暴 。比如我要给球员添加一个 体重 属性, 这时你会发现, 要同时修改两个方法
toStringXML()、toUserXMLDO() 的实现 修改如下 :
private Double weight;
toStringXML() : sb.append(genNodeXmlString("weight", userXMLDO.getName()));
toUserXMLDO() :
for(Iterator<?> it = rootElement.elementIterator("weight"); it.hasNext();) {
Element element = (Element) it.next();
userXMLDO.setHeight(Double.valueOf(element.getText()));
}
添加1个属性,改起来还是可以接受, 添加2个属性,还是可以接受的、....... 再添加100个属性呢?不能接受了吧~
二: 方案② 用反射
添加类型枚举
package test.reflect2; import java.util.HashMap;
import java.util.Map; public enum NodeEnum { userName("name", String.class),
password("password", String.class),
userId("id", Long.class),
height("height", Double.class),
; NodeEnum(String name, Class<?> type) {
this.name = name;
this.type = type;
} public static Map<String, Class<?>> getNodeMap() {
Map<String, Class<?>> map = new HashMap<String, Class<?>>();
NodeEnum[] nodeEnums = NodeEnum.values();
for (NodeEnum ne : nodeEnums) {
map.put(ne.getName(), ne.getType());
}
return map;
} private String name; private Class<?> type; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Class<?> getType() {
return type;
} public void setType(Class<?> type) {
this.type = type;
} }
实体类添加
public class UserXMLDO {
private static Map<String, Class<?>> nodeEnumMap = null;
static {
nodeEnumMap = NodeEnum.getNodeMap();
}
private Long id;
private String name;
private String password;
private Double height;
private Double weight;
public static String toStringXML(UserXMLDO userXMLDO) throws Exception {
StringBuffer sb = new StringBuffer();
sb.append("<UserInfo>");
Iterator<Entry<String, Class<?>>> it = nodeEnumMap.entrySet().iterator();
while (it.hasNext()) {
Entry<String, Class<?>> entry = it.next();
Object object = userXMLDO.getClass().getDeclaredField(entry.getKey()).get(userXMLDO);
sb.append(genNodeXmlString(entry.getKey(), object == null ? "" : object));
}
sb.append("</UserInfo>");
return sb.toString();
}
public static UserXMLDO toUserXMLDO(String xml) throws Exception {
UserXMLDO userXMLDO = new UserXMLDO();
Element rootElement = DocumentXmlHelper.read(xml).getRootElement();
Iterator<?> it = rootElement.elementIterator();
while (it.hasNext()) {
Element e = (Element) it.next();
setAttrValue(userXMLDO, e.getName(), e.getTextTrim());
}
return userXMLDO;
}
private static void setAttrValue(UserXMLDO userXMLDO, String nodeName, String value) throws Exception {
Field f = userXMLDO.getClass().getDeclaredField(nodeName);
if (nodeEnumMap.get(nodeName).getName().equals(String.class.getName())) {
f.set(userXMLDO, value);
} else if (nodeEnumMap.get(nodeName).getName().equals(Long.class.getName())
|| nodeEnumMap.get(nodeName).getName().equals(Double.class.getName())) {
f.set(userXMLDO,
nodeEnumMap.get(nodeName).getDeclaredMethod("valueOf", String.class).invoke(userXMLDO, value));
} else {
throw new Exception("仅支持Long, String 类型");
}
}
private static String genNodeXmlString(String nodeName, Object value) {
StringBuffer sb = new StringBuffer();
sb.append("<");
sb.append(nodeName);
sb.append(">");
sb.append(value);
sb.append("</");
sb.append(nodeName);
sb.append(">");
return sb.toString();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
}
test :
public static void main(String[] args) throws Exception {
UserXMLDO userXMLDO = new UserXMLDO();
userXMLDO.setId(1L);
userXMLDO.setName("威少");
userXMLDO.setPassword("三双无解");
userXMLDO.setHeight(1.90d);
userXMLDO.setWeight(85.5d);
String xml = UserXMLDO.toStringXML(userXMLDO);
System.out.println(xml);
UserXMLDO userXMLDO2 = UserXMLDO.toUserXMLDO(xml);
System.out.println(userXMLDO2);
}
方案② , 体现出了很多灵活性, 把 可变 与 不可变 code 抽取出来了, 可能这样说, 或许有点难理解, 我就针对这种做法, 举个例子...
如 : 我要球员添加一个 体重 属性, 这是你会发现, 不用去修改
toStringXML()、toUserXMLDO() 的实现 你只要在 NodeEnum 增加一个类型定义即可 :
weight("weight", Double.class),
素不素改动很小, 如果换一个新人来接手维护, 每次有新的属性需求添加, 他可以很快添加完成, 不需要去改方法的实现, 这样就相对稳定了~~很巧妙做到“以不变应万变”!!
三、总结
相信比较上述两种方案后, 你会觉得反射有时特别好用, 让代码更加健硕, 但是也要记住, 不要一味盲目, 甚至刻意去使用反射, 因为性能差是反射的一大弊端!要权衡评估下。
java反射快速入门(二)的更多相关文章
- java反射快速入门(一)
本文会从以下几个方面讲起 ① 反射的简单解释 ② java反射的API接口 及 demo ③ 反射的优缺点.应用场景 一.什么是反射? java反射:在程序运行中动态获取类的信息,及动态调用对象的方法 ...
- java反射快速入门
笔记记在了掘金,发现掘金的markdown编辑器比博客园样式要好看不少 https://juejin.im/post/5d4e575af265da03e4674e9f
- JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
JAVA WEB快速入门系列之前的相关文章如下:(文章全部本人[梦在旅途原创],文中内容可能部份图片.代码参照网上资源) 第一篇:JAVA WEB快速入门之环境搭建 第二篇:JAVA WEB快速入门之 ...
- JAVA WEB快速入门之从编写一个基于SpringMVC框架的网站了解Maven、SpringMVC、SpringJDBC
接上篇<JAVA WEB快速入门之通过一个简单的Spring项目了解Spring的核心(AOP.IOC)>,了解了Spring的核心(AOP.IOC)后,我们再来学习与实践Maven.Sp ...
- Java Web快速入门——全十讲
Java Web快速入门——全十讲 这是一次培训的讲义,就是我在给学生讲的过程中记录下来的,非常完整,原来发表在Blog上,我感觉这里的学生可能更需要. 内容比较长,你可以先收藏起来,慢慢看. 第一讲 ...
- JAVA WEB快速入门之通过一个简单的Spring项目了解Spring的核心(AOP、IOC)
接上篇<JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构.调试.部署>,通过一个简单的JSP WEB网站了解了JAVA WEB相关的知识,比如:Ser ...
- JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构、调试、部署
接上篇<JAVA WEB快速入门之环境搭建>,在完成了环境搭建后(JDK.Tomcat.IDE),现在是万事具备,就差写代码了,今天就来从编写一个JSP WEB网站了解JSP WEB网站的 ...
- java反射机制入门01
java反射机制入门是我从极客学院的视频中学习的. 1.反射机制背景概述 反射(Reflection)是java被视为动态(或准动态)语言的一个关键性质.反射机制指的是程序在运行时能够获取任何类的内部 ...
- 大白话说Java反射:入门、使用、原理
文章首发于[博客园-陈树义],点击跳转到原文<大白话说Java反射:入门.进阶.原理> 反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释. 一般情况下,我们使用某个类时 ...
随机推荐
- etc/ld.so.conf的使用说明
这个文件记录了编译时使用的动态链接库的路径.默认情况下,编译器只会使用/lib和/usr/lib这两个目录下的库文件如果你安装了某些库,比如在安装gtk+-2.4.13时它会需要glib-2.0 &g ...
- R语言笔记:快速入门
1.简单会话 > x<-c(1,2,4) > x [1] 1 2 4 R语言的标准赋值运算符是<-.也可以用=,不过不建议用它,有些情况会失灵.其中c表示连接(concaten ...
- 中断服务程序不用interrupt关键字也可实现中断,该关键字是否必须?
2013-06-20 11:13:35 中断服务程序不用interrupt关键字也可实现中断,该关键字是否必须? 使用tools->pin connect,将INT5与pin.txt关联,模拟外 ...
- MCC(移动国家码)和 MNC(移动网络码)
国际移动用户识别码(IMSI) international mobile subscriber identity 国际上为唯一识别一个移动用户所分配的号码. 从技术上讲,IMSI可以彻底解决国 ...
- Counting sheep...
Counting sheep... Description: Consider an array of sheep where some sheep may be missing from their ...
- bzoj2324
出题人真 口袋迷 很容易发现这是一道费用流的题目 很显然这个问题有两个难点: 保证走到某个点时之前序号的点都被走过 保证每个点都走 对于1,我们换个说法,一个人走到该点时经过的点的序号都小于该点--- ...
- Dataguard Content
1.Dataguard环境设计的三个重要概念 1.1 Primary数据库 在Data Guard的环境中与Standby数据库对应的数据库即是Primary数据库,也就是Primary数据库正在运行 ...
- jquery M97-datepicker日历控件
My97DatePicker是一款非常灵活好用的日期控件.使用非常简单. 1.下载My97DatePicker组件包 2.在页面中引入该组件js文件: <script type=&quo ...
- expunge
expunge 擦掉: 除去: 删去: 消除 1. The experience was something he had tried to expunge from his memory. 他曾努力 ...
- dll打包进需要发布的exe z
http://www.cnblogs.com/Jarvin/p/3721195.html 我们需要发布的exe文件很多时候都可能会依赖于一堆松散的dll,如果想在发布 的时候只提供exe文件,而不想把 ...