上一遍博文 , 简单介绍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反射快速入门(二)的更多相关文章

  1. java反射快速入门(一)

    本文会从以下几个方面讲起 ① 反射的简单解释 ② java反射的API接口 及 demo ③ 反射的优缺点.应用场景 一.什么是反射? java反射:在程序运行中动态获取类的信息,及动态调用对象的方法 ...

  2. java反射快速入门

    笔记记在了掘金,发现掘金的markdown编辑器比博客园样式要好看不少 https://juejin.im/post/5d4e575af265da03e4674e9f

  3. JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

    JAVA WEB快速入门系列之前的相关文章如下:(文章全部本人[梦在旅途原创],文中内容可能部份图片.代码参照网上资源) 第一篇:JAVA WEB快速入门之环境搭建 第二篇:JAVA WEB快速入门之 ...

  4. JAVA WEB快速入门之从编写一个基于SpringMVC框架的网站了解Maven、SpringMVC、SpringJDBC

    接上篇<JAVA WEB快速入门之通过一个简单的Spring项目了解Spring的核心(AOP.IOC)>,了解了Spring的核心(AOP.IOC)后,我们再来学习与实践Maven.Sp ...

  5. Java Web快速入门——全十讲

    Java Web快速入门——全十讲 这是一次培训的讲义,就是我在给学生讲的过程中记录下来的,非常完整,原来发表在Blog上,我感觉这里的学生可能更需要. 内容比较长,你可以先收藏起来,慢慢看. 第一讲 ...

  6. JAVA WEB快速入门之通过一个简单的Spring项目了解Spring的核心(AOP、IOC)

    接上篇<JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构.调试.部署>,通过一个简单的JSP WEB网站了解了JAVA WEB相关的知识,比如:Ser ...

  7. JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构、调试、部署

    接上篇<JAVA WEB快速入门之环境搭建>,在完成了环境搭建后(JDK.Tomcat.IDE),现在是万事具备,就差写代码了,今天就来从编写一个JSP WEB网站了解JSP WEB网站的 ...

  8. java反射机制入门01

    java反射机制入门是我从极客学院的视频中学习的. 1.反射机制背景概述 反射(Reflection)是java被视为动态(或准动态)语言的一个关键性质.反射机制指的是程序在运行时能够获取任何类的内部 ...

  9. 大白话说Java反射:入门、使用、原理

    文章首发于[博客园-陈树义],点击跳转到原文<大白话说Java反射:入门.进阶.原理> 反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释. 一般情况下,我们使用某个类时 ...

随机推荐

  1. P154、面试题28:字符串的排列

    题目:输入一个字符串,打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a.b.c所能排列出来的所有字符串abc.acb.bac.bca.cab.cba. 测试用例: 1)功能测试( ...

  2. 对Cost (%CPU) 粗略的理解

    今天研究执行计划,看到执行计划里面有Cost (%CPU),我这边研究了一把,不知道对与否,拿出来晒晒 在Oracle 10g中,Oracle 把CPU的cost也统计在执行计划中去了, 这和以前的8 ...

  3. Android 签名(4)验证是否签名

    判断Apk是否签名 用命令:jarsigner -verify  XXX.apk 增加 -verbose -certs 两个选项可显示更多信息. 如果有Android Debug字樣就是debug 如 ...

  4. 【HDOJ】4029 Distinct Sub-matrix

    思路是枚举矩阵列数,然后将字符矩阵转换成字符串,通过字符数组求不同子串数目.最后,减去不成立的情况.使用特殊字符分割可能的组合. /* 4029 */ #include <iostream> ...

  5. Struts2国际化文件乱码解决

    方法1:使用native2ascii进行编码转换 代码如下: native2ascii -encoding UTF-8 GlobalMessages.properties NewGlobalMessa ...

  6. Mac修改用户名

    Mac 修改用户是一件很悲剧的事,因为牵涉到很多地方的修改,当然,如果只是需要满足登陆用户名的修改的话,就比较简单.而如果需要将某个用户在每一个地方显示的名字都改掉的话,就要修改不是地方了,下面就来讲 ...

  7. poj3308Paratroopers(dinic)

    http://poj.org/problem?id=3308 给两个定义 最小割:对于图中的两个点(一般为源点和汇点)来说,如果把图中的一些边去掉,如果它们之间无法连通的话,则这些边组成的集合就叫为割 ...

  8. 【 D3.js 高级系列 — 5.1 】 颜色插值和线性渐变

    颜色插值指的是给出两个 RGB 颜色值,两个颜色之间的值通过插值函数计算得到.线性渐变是添加到 SVG 图形上的过滤器,只需给出两端的颜色值即可. 1. 颜色插值 在[高级 - 第 5.0 章]里已经 ...

  9. 陈正冲老师对于c语言野指针的解释

    那到底什么是野指针呢?怎么去理解这个“野”呢?我们先看别的两个关于“野”的词: 野孩子:没人要,没人管的孩子:行为动作不守规矩,调皮捣蛋的孩子.野狗:没有主人的狗,没有链子锁着的狗,喜欢四处咬人. 对 ...

  10. Android学习系列(22)--App主界面比较

    本文算是一篇漫谈,谈一谈当前几个流行应用的主界面布局,找个经典的布局我们自己也来实现一个.不是为了追求到底有多难,而是为了明白我们确实需要这么做. 走个题,android的UI差异化市场依然很大,依然 ...