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反射:入门.进阶.原理> 反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释. 一般情况下,我们使用某个类时 ...
随机推荐
- DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录(转)
http://www.cnblogs.com/LittleHann/p/3828927.html 相关学习资料 http://baike.baidu.com/link?url=77B3BYIuVsB3 ...
- Xcode中的iOS工程模板
1. Application类型 我们大部分的开发工作都是从使用Application类型模板创建iOS程序开始的.该类型共包含7个模板,具体如下所示. Master-Detail Applicati ...
- java ServerSocket服务端编程
public class Test { public static void main(String[] args) throws Exception{ //1. 构造ServerSocket实例,指 ...
- php 对象的执行
1.BNF范式 %token T_OBJECT_OPERATOR "-> (T_OBJECT_OPERATOR)" unticked_statement: | expr TS ...
- storm - 基础概念整理
理论 Hadoop的出现虽然为大数据计算提供了一条捷径,但其仍然存在自身难以克服的缺点:实时性不足.Hadoop的一轮计算的启动需要较长时间,因此其满足不了对实时性有较高要求的场景. Storm由此应 ...
- 使用委托的BeginInvoke方法来完成复杂任务的操作
现在假设我有这样一个窗体(包含一个进度条和一个按钮与两个文本框),在第一个文本框中输入一个数字进行阶乘运算,在此过程中进度条与运算进度保持一致,同时可以在第二个文本框中进行其它工作(比如输入).对付这 ...
- SCI杂志分区规则
1区:该期刊的影响因子排名位于其所在学科排名的前5% 2区:该期刊的影响因子排名位于其所在学科排名的前20%但未进入5% 3区:该期刊的影响因子排名位于其所在学科排名的前50%但未进入20%的 4区: ...
- DB面试题
1.如何让SELECT 查询结果额外增加自动递增序号 select * from ( select a.姓名, a.成绩, (select count(id) from 表 where 成绩>= ...
- 刑事案件的构成要素 zt
论刑事案件的构成要素 马忠红 2013-03-22 14:05:33 来源:<中国人民公安大学学报:社会科学版>(京)2012年5期 [内容提要]刑事案件是由诸多要素构成的一个系 统. ...
- sublime3安装python插件 -- SublimeCodeIntel
先装Package Control,类似pip的一个索引安装工具. 1.http://sublime.wbond.net/Package%20Control.sublime-package 2.sub ...