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反射:入门.进阶.原理> 反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释. 一般情况下,我们使用某个类时 ...
随机推荐
- Java API ——String类
1.String类概述 · 字符串是由多个字符组成的一串数据(字符序列),也可以看成是一个字符数组. · 字符串字符值“abc”也可以看成是一个字符串对象. · 字符串是常量,一旦被赋值,就不能被改变 ...
- Playing with cubes II
Description: Hey Codewarrior! You already implemented a Cube class, but now we need your help again! ...
- poj 2409 Let it Bead && poj 1286 Necklace of Beads(Polya定理)
题目:http://poj.org/problem?id=2409 题意:用k种不同的颜色给长度为n的项链染色 网上大神的题解: 1.旋转置换:一个有n个旋转置换,依次为旋转0,1,2,```n-1. ...
- 函数fsp_alloc_seg_inode
从inode page中申请inode entry inode = fsp_alloc_seg_inode(space_header, mtr); /************************* ...
- 数论/the second wave
扩展欧几里得算法. void exgcd(int a,int b,int&x,int&y){ if(!b) { x=1;y=0;return ; } exgcd(b,a%b,x,y); ...
- 三个流行MySQL分支的对比
MySQL是历史上最受欢迎的免费开源程序之一.它是成千上万个网站的数据库骨干,并且可以将它(和Linux)作为过去10年里Internet呈指数级增长的一个有力证明. 那么,如果MySQL真的这么重要 ...
- Springmvc构造RESTful详细讲解
Rest介绍 /blog/1 HTTP GET => 得到id = 1的blog/blog/1 HTTP DELETE => 删除 id = 1的blog/blog/1 HTTP PUT ...
- WCF 服务调用RFC 出现异常
我在VS2010的WCF项目用connecter 3.0 调用 RFC 运行到 IDestinationConfiguration ID = new SAPConfig(); ...
- hdu 3367 Pseudoforest
Pseudoforest Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) To ...
- ubuntu桌面右上角键盘图标不见解决方法
今天出现了这个问题,桌面右上角的键盘图标不见,找到解决方法如下: 打开终端,分别输入以下命令即可: killall ibus-daemon 这个表示结束进程 ibus-daemon -d 这个表示重启 ...