java反射原理制作对象打印工具
程序员文章站
2024-03-07 16:12:03
主要运用java反射原理,格式化输出java对象属性值,特别是list 和map。
mytestutil.java
package utils;...
主要运用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)); } }