首页 > 编程 > Java > 正文

java反射原理制作对象打印工具

2019-11-26 14:46:54
字体:
来源:转载
供稿:网友

主要运用java反射原理,格式化输出java对象属性值,特别是list 和map。

 MyTestUtil.java

package utils; import java.lang.reflect.Field;import java.text.SimpleDateFormat;import java.util.Arrays;import java.util.Collection;import java.util.Date;import java.util.Iterator;import java.util.Map;import java.util.Map.Entry;  /** * 这个类是方便控制台输出object,主要应用java反射机制。 因为考虑到使用性和美观性,没有使用无限递归。 * 而是在toStr方法中加入一个boolean recursion ,是否递归。 * 当然我们也可以将boolean recursion换成int recursion,控制递归次数。 * 其实就我使用经验来看,复杂数据toString,用json工具转化成json输出是一个不错的方式。  //这是我用的方式,boolean recursion是否递归  public static int add(int i,boolean recursion){    sum+=i;    if(recursion)      add(i, false);    return sum;  }  //也可以这样,int recursion表示递归次数  public static int add(int i,int recursion){    sum+=i;    if(recursion>0){      recursion--;      add(i, recursion);    }    return sum;  } *  *  * @author klguang *  */   public class MyTestUtil {    static final String SPLIT_LINE = "=";// 分割线  static final String MY_SIGN = "KLG_print";//默  private static String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";   /**   * 将集合类型toSring方法   * @param object   * @param recursion   *      是否递归   * @return   */  private static String collectionToStr(Object object, boolean recursion) {    if (object == null)      return "null";    Object[] a = null;    // 将集合类型转换成数组类型    if (isArrayType(object))      a = (Object[]) object;    else      a = ((Collection) object).toArray();    if (isSimpleArr(a) || !recursion)      return Arrays.toString(a);    else      return complexArrToStr(a);  }   /**   * Arrays有toString方法,但是对象内容太多,在一行显示 还有就是没有显示index信息   */  private static String complexArrToStr(Object[] a) {    if (a == null)      return "null";     int iMax = a.length - 1;    if (iMax == -1)      return "[]";     StringBuilder b = new StringBuilder();    for (int i = 0;; i++) {      String value = objToStr(a[i], false);      b.append("[" + i + "]" + " -> " + value);      if (i == iMax)        return b.toString();      b.append(", /r/n");    }  }   /**   * map类型toString方法   *    * @param map   * @param recursion   *      是否递归   * @return   */  private static String mapToStr(Map<String, Object> map, boolean recursion) {    if (map == null)      return "null";    if (isSimpleMap(map) || !recursion)      return simpleMapToStr(map);    else      return complexMapToStr(map, true);  }   /**   * map的value是简单类型的,复制Map.toString,我给它加了换行10个换行   *    * @param map   * @return   */  private static String simpleMapToStr(Map map) {    Iterator<Entry<String, Object>> i = map.entrySet().iterator();    if (!i.hasNext())      return "{}";     StringBuilder sb = new StringBuilder();    sb.append('{');    for (int t = 1;; t++) {      Entry<String, Object> e = i.next();      sb.append(e.getKey()).append(" = ").append(e.getValue());      if (!i.hasNext())        return sb.append('}').toString();      sb.append(',').append(' ');      if (t % 10 == 0 && t != 0)        sb.append("/r/n ");    }  }   private static String complexMapToStr(Map map, boolean recursion) {    Iterator<Entry<String, Object>> i = map.entrySet().iterator();    if (!i.hasNext())      return "{}";    StringBuilder sb = new StringBuilder();    sb.append("{/r/n");    for (int t = 1;; t++) {      Entry<String, Object> e = i.next();      String key = String.valueOf(e.getKey());      Object value = e.getValue();      sb.append(indent(2," ")).append(key).append(" = ");      if (isSimpleType(value) || !recursion)        sb.append(String.valueOf(value));      else        sb.append(objToStr(value, false));      if (!i.hasNext())        return sb.append("/r/n}").toString();      sb.append(',').append("/r/n");    }  }   /**   *    *    * @param object   * @param recursion   *      是否要递归   * @return   */  private static String beanToStr(Object object, boolean recursion) {    if (object == null)      return "null";    Class clazz = object.getClass();    StringBuilder sb = new StringBuilder();    //返回源代码中给出的底层类的简称    sb.append(clazz.getSimpleName()).append("[");    Field[] fields = sortFieldByType(clazz.getDeclaredFields());    int iMax = fields.length - 1;    if (iMax == -1)      return sb.append("]").toString();    for (int i = 0;; i++) {      Field field = fields[i];      field.setAccessible(true);// 设置些属性是可以访问的      String name = field.getName();// 取得field的名称      if (name.equals("serialVersionUID"))        continue;      try {        Object value = field.get(object);// 得到此属性的值        if (isSimpleType(value) || !recursion)          sb.append(name + " = " + String.valueOf(value));        else          sb.append("/r/n" + indent(clazz.getSimpleName().length() + 2," ")              + objToStr(value, false) + "/r/n");      } catch (Exception e) {        e.printStackTrace();      }      if (i == iMax)        return sb.append("]").toString();      sb.append(",");    }  }     private static String indent(int length,String sign) {    StringBuilder sb = new StringBuilder();    for (int i = 0; i < length; i++) {      sb.append(sign);    }    return sb.toString();  }   private static boolean isSimpleType(Object obj) {    if (obj == null)      return true;    else {      Class objectClass = obj.getClass();      return isSimpleType(objectClass);    }  }   /**   *    * @param objectClass   *      用obj.getClass()取得   * @return   */  private static boolean isSimpleType(Class objectClass) {    if (objectClass == boolean.class || objectClass == Boolean.class        || objectClass == short.class || objectClass == Short.class        || objectClass == byte.class || objectClass == Byte.class        || objectClass == int.class || objectClass == Integer.class        || objectClass == long.class || objectClass == Long.class        || objectClass == float.class || objectClass == Float.class        || objectClass == char.class || objectClass == Character.class        || objectClass == double.class || objectClass == Double.class        || objectClass == String.class) {      return true;    } else {      return false;    }  }   /**   * Method isCollectionType   *    * @param obj   *      Object   * @return boolean   */  private static boolean isCollectionType(Object obj) {    if (obj == null)      return false;    return (obj.getClass().isArray() || (obj instanceof Collection));  }   private static boolean isArrayType(Object obj) {    if (obj == null)      return false;    return (obj.getClass().isArray());  }   private static boolean isMapType(Object obj) {    if (obj == null)      return false;    return (obj instanceof Map);  }     private static boolean isDateType(Object obj){    if(obj==null)      return false;    return (obj instanceof Date);  }     private static boolean isBeanType(Object obj) {    if (isSimpleType(obj) || isCollectionType(obj) || isMapType(obj))      return false;    else      return true;  }   private static boolean isSimpleArr(Object[] a) {    if (a == null || a.length < 1)      return true;    boolean flag = true;    for (Object o : a) {      if (!isSimpleType(o)) {        flag = false;        break;      }    }    return flag;  }   private static boolean isSimpleMap(Map map) {    if (map == null)      return true;    Iterator<Entry<String, Object>> i = map.entrySet().iterator();    boolean flag = true;    while (i.hasNext()) {      Entry<String, Object> e = i.next();      if (!isSimpleType(e.getValue())) {        flag = false;        break;      }    }    return flag;  }   /***   * 将简单类型排在前面   * @param fields   * @return   */   public static Field[] sortFieldByType(Field[] fields) {    for (int i = 0; i < fields.length; i++) {      if (isSimpleType(fields[i].getType()))        continue;// fields[i]是简单类型不管      // fields[i]是复杂类型      // int j = i+1,从fields[i]之后开始比较      for (int j = i + 1; j < fields.length; j++) {        Field fieldTmp = null;        if (isSimpleType(fields[j].getType())) {// 与后面的第一个简单类型交互          fieldTmp = fields[i];          fields[i] = fields[j];          fields[j] = fieldTmp;          break; // 后面的循环,是没有意义de        }      }    }    return fields;  }   /**   * 这个方法是递归方法,并且并多个地方调用,考虑到循环引用和显示格式, boolean recursion取得确保递归可以被终止。   *    * @param object   * @param recursion   *      是否需要更深一层显示   * @return   */  private static String objToStr(Object object, boolean recursion) {    if (object == null)      return "null";    object.toString();    if(isDateType(object))      return new SimpleDateFormat(DATE_FORMAT).format((Date)object);    else if (isBeanType(object))      return beanToStr(object, recursion);    else if (isCollectionType(object))      return collectionToStr(object, recursion);    else if (isMapType(object))      return mapToStr((Map) object, recursion);    else      return String.valueOf(object);  }   public static String objToStr(Object obj) {    return objToStr(obj, true);  }   private static void print(Object obj,String sign,String content) {    String begin=indent(15, SPLIT_LINE) + " " +obj.getClass().getSimpleName()      + " >> " + sign + " " + indent(10, SPLIT_LINE);    int length=(begin.length()-sign.length()-5)/2;         String end=indent(length, SPLIT_LINE)+ " " + sign + " " + indent(length, SPLIT_LINE);    System.out.println(begin+"/r/n"+content+"/r/n"+end);       }  public static void print(Object obj){    print(obj,MY_SIGN,objToStr(obj));  }  public static void printWithSign(String sign, Object obj) {    print(obj, sign,objToStr(obj));  }}

不过呢上面代码太繁琐了,没有考虑多种类型嵌套的问题。
数组类型强转会报ClassCastException 。
平常打日志就用log4j写个工具方法 比上面这个清晰明了多了。

public static void debug(String message,Object o){int count=0;if(o==null){LOGGER.debug(chain(message,": null"));return;}if(o.getClass().isArray()){for(int i=0,len=Array.getLength(o);i<len;i++){debug(chain(message,"-[",i,"]"),Array.get(o, i));}}else if(o instanceof Map){Entry<?,?> e;for(Iterator<?> it=((Map<?,?>)o).entrySet().iterator();it.hasNext();){e=(Entry<?,?>) it.next();debug(chain(message,"-[K:",e.getKey(),"]"),e.getValue());}}else if(o instanceof Iterable){for(Iterator<?> it=((Iterable<?>) o).iterator();it.hasNext();){count++; debug(chain(message,"-[",count,"]"),it.next());}}else{LOGGER.debug(chain(message,":",o));}}

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表