• 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个属性呢?不能接受了吧~

    二: 方案② 用反射

    添加类型枚举

     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),

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


    三、总结

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

  • 相关阅读:
    C if语句判断年龄
    C 计算时间差
    C 计算身高
    JRebel激活破解完美解决方式
    Maven optional和scope
    判断当前时间是否在某个时间段内
    给定时间加上几个小时
    RabbitMQ学习笔记
    浏览器、服务器会话
    Maven核心知识点梳理
  • 原文地址:https://www.cnblogs.com/chenmo-xpw/p/5183320.html
Copyright © 2020-2023  润新知