java反射快速入门(二)

来源:互联网 发布:linux 命令 选项 编辑:程序博客网 时间:2024/06/03 23:06
上一遍博文 , 简单介绍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个属性呢?不能接受了吧~

二: 方案② 用反射

添加类型枚举

 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 }
View Code

实体类添加 

  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 }
View Code

 

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     }
View Code

 

方案② , 体现出了很多灵活性, 把 可变 与 不可变 code 抽取出来了, 可能这样说, 或许有点难理解, 我就针对这种做法, 举个例子... 

如 : 我要球员添加一个 体重 属性, 这是你会发现, 不用去修改

toStringXML()、toUserXMLDO() 的实现

你只要在 NodeEnum 增加一个类型定义即可 :

weight("weight", Double.class),

素不素改动很小, 如果换一个新人来接手维护, 每次有新的属性需求添加, 他可以很快添加完成, 不需要去改方法的实现, 这样就相对稳定了~~很巧妙做到“以不变应万变”!!


三、总结

相信比较上述两种方案后, 你会觉得反射有时特别好用, 让代码更加健硕, 但是也要记住, 不要一味盲目, 甚至刻意去使用反射, 因为性能差是反射的一大弊端!要权衡评估下。

 

0 0