java反射快速入门(二)
来源:互联网 发布:linux 命令 选项 编辑:程序博客网 时间:2024/06/03 23:06
上一遍博文 , 简单介绍java 反射的常用接口,本遍博文, 我会结合项目开发的实际例子讲解下 java反射的使用View CodeView CodeView Code
现在有个需求, 要将一个对象转换成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个属性呢?不能接受了吧~
二: 方案② 用反射
添加类型枚举
1 package test.reflect2; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 public enum NodeEnum { 7 8 userName("name", String.class), 9 password("password", String.class),10 userId("id", Long.class),11 height("height", Double.class),12 ;13 14 NodeEnum(String name, Class<?> type) {15 this.name = name;16 this.type = type;17 }18 19 public static Map<String, Class<?>> getNodeMap() {20 Map<String, Class<?>> map = new HashMap<String, Class<?>>();21 NodeEnum[] nodeEnums = NodeEnum.values();22 for (NodeEnum ne : nodeEnums) {23 map.put(ne.getName(), ne.getType());24 }25 return map;26 }27 28 private String name;29 30 private Class<?> type;31 32 public String getName() {33 return name;34 }35 36 public void setName(String name) {37 this.name = name;38 }39 40 public Class<?> getType() {41 return type;42 }43 44 public void setType(Class<?> type) {45 this.type = type;46 }47 48 49 }
实体类添加
1 public class UserXMLDO { 2 3 private static Map<String, Class<?>> nodeEnumMap = null; 4 static { 5 nodeEnumMap = NodeEnum.getNodeMap(); 6 } 7 8 private Long id; 9 private String name; 10 private String password; 11 private Double height; 12 private Double weight; 13 14 public static String toStringXML(UserXMLDO userXMLDO) throws Exception { 15 StringBuffer sb = new StringBuffer(); 16 sb.append("<UserInfo>"); 17 Iterator<Entry<String, Class<?>>> it = nodeEnumMap.entrySet().iterator(); 18 while (it.hasNext()) { 19 Entry<String, Class<?>> entry = it.next(); 20 Object object = userXMLDO.getClass().getDeclaredField(entry.getKey()).get(userXMLDO); 21 sb.append(genNodeXmlString(entry.getKey(), object == null ? "" : object)); 22 } 23 sb.append("</UserInfo>"); 24 return sb.toString(); 25 } 26 27 public static UserXMLDO toUserXMLDO(String xml) throws Exception { 28 UserXMLDO userXMLDO = new UserXMLDO(); 29 Element rootElement = DocumentXmlHelper.read(xml).getRootElement(); 30 31 Iterator<?> it = rootElement.elementIterator(); 32 while (it.hasNext()) { 33 Element e = (Element) it.next(); 34 setAttrValue(userXMLDO, e.getName(), e.getTextTrim()); 35 } 36 return userXMLDO; 37 } 38 39 private static void setAttrValue(UserXMLDO userXMLDO, String nodeName, String value) throws Exception { 40 41 Field f = userXMLDO.getClass().getDeclaredField(nodeName); 42 if (nodeEnumMap.get(nodeName).getName().equals(String.class.getName())) { 43 f.set(userXMLDO, value); 44 } else if (nodeEnumMap.get(nodeName).getName().equals(Long.class.getName()) 45 || nodeEnumMap.get(nodeName).getName().equals(Double.class.getName())) { 46 f.set(userXMLDO, 47 nodeEnumMap.get(nodeName).getDeclaredMethod("valueOf", String.class).invoke(userXMLDO, value)); 48 } else { 49 throw new Exception("仅支持Long, String 类型"); 50 } 51 } 52 53 54 private static String genNodeXmlString(String nodeName, Object value) { 55 StringBuffer sb = new StringBuffer(); 56 sb.append("<"); 57 sb.append(nodeName); 58 sb.append(">"); 59 sb.append(value); 60 sb.append("</"); 61 sb.append(nodeName); 62 sb.append(">"); 63 return sb.toString(); 64 } 65 66 public Long getId() { 67 return id; 68 } 69 70 public void setId(Long id) { 71 this.id = id; 72 } 73 74 public String getName() { 75 return name; 76 } 77 78 public void setName(String name) { 79 this.name = name; 80 } 81 82 public String getPassword() { 83 return password; 84 } 85 86 public void setPassword(String password) { 87 this.password = password; 88 } 89 90 public Double getHeight() { 91 return height; 92 } 93 94 public void setHeight(Double height) { 95 this.height = height; 96 } 97 98 public Double getWeight() { 99 return weight;100 }101 102 public void setWeight(Double weight) {103 this.weight = weight;104 }105 }
test :
1 public static void main(String[] args) throws Exception { 2 UserXMLDO userXMLDO = new UserXMLDO(); 3 userXMLDO.setId(1L); 4 userXMLDO.setName("威少"); 5 userXMLDO.setPassword("三双无解"); 6 userXMLDO.setHeight(1.90d); 7 userXMLDO.setWeight(85.5d); 8 9 String xml = UserXMLDO.toStringXML(userXMLDO);10 System.out.println(xml);11 12 UserXMLDO userXMLDO2 = UserXMLDO.toUserXMLDO(xml);13 System.out.println(userXMLDO2);14 }
方案② , 体现出了很多灵活性, 把 可变 与 不可变 code 抽取出来了, 可能这样说, 或许有点难理解, 我就针对这种做法, 举个例子...
如 : 我要球员添加一个 体重 属性, 这是你会发现, 不用去修改
toStringXML()、toUserXMLDO() 的实现
你只要在 NodeEnum 增加一个类型定义即可 :
weight("weight", Double.class),
素不素改动很小, 如果换一个新人来接手维护, 每次有新的属性需求添加, 他可以很快添加完成, 不需要去改方法的实现, 这样就相对稳定了~~很巧妙做到“以不变应万变”!!
三、总结
相信比较上述两种方案后, 你会觉得反射有时特别好用, 让代码更加健硕, 但是也要记住, 不要一味盲目, 甚至刻意去使用反射, 因为性能差是反射的一大弊端!要权衡评估下。
0 0
- java反射快速入门(二)
- java反射快速入门(二)
- java反射快速入门(一)
- java反射快速入门(一)
- Java反射基础 入门(二)
- Java多线程 快速入门(二)
- java反射(二)
- Java 反射(二)
- Java反射(二):反射的使用
- Struts快速入门(二)
- Struts快速入门(二)
- Struts快速入门(二)
- Struts快速入门(二)
- Struts快速入门(二)
- NUnit快速入门(二)
- Struts快速入门(二)
- Firebug快速入门(二)
- Delphi快速入门(二)
- java反射快速入门(一)
- 数论学习之乘法逆元
- 字符串结束标志
- Ajax实现xml文件数据插入数据库(三)---javabean实现数据库插入
- 数论学习之欧几里得的应用
- java反射快速入门(二)
- char,string和CString转换
- 告别2015, 展望2016
- 字符串赋值操作
- 传话
- 从标准输出和读入
- 邮票面值设计
- Android 文件的权限,以及跨应用读取文件
- maven快速入门