java反射原理制作對(duì)象打印工具
主要運(yùn)用java反射原理,格式化輸出java對(duì)象屬性值,特別是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; /** * 這個(gè)類是方便控制臺(tái)輸出object,主要應(yīng)用java反射機(jī)制。 因?yàn)榭紤]到使用性和美觀性,沒(méi)有使用無(wú)限遞歸。 * 而是在toStr方法中加入一個(gè)boolean recursion ,是否遞歸。 * 當(dāng)然我們也可以將boolean recursion換成int recursion,控制遞歸次數(shù)。 * 其實(shí)就我使用經(jīng)驗(yàn)來(lái)看,復(fù)雜數(shù)據(jù)toString,用json工具轉(zhuǎn)化成json輸出是一個(gè)不錯(cuò)的方式。 //這是我用的方式,boolean recursion是否遞歸 public static int add(int i,boolean recursion){ sum+=i; if(recursion) add(i, false); return sum; } //也可以這樣,int recursion表示遞歸次數(shù) 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";//默認(rèn)標(biāo)記 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; // 將集合類型轉(zhuǎn)換成數(shù)組類型 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方法,但是對(duì)象內(nèi)容太多,在一行顯示 還有就是沒(méi)有顯示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是簡(jiǎn)單類型的,復(fù)制Map.toString,我給它加了換行10個(gè)換行 * * @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(); //返回源代碼中給出的底層類的簡(jiǎn)稱 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);// 設(shè)置些屬性是可以訪問(wèn)的 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; } /*** * 將簡(jiǎn)單類型排在前面 * @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]是簡(jiǎn)單類型不管 // fields[i]是復(fù)雜類型 // int j = i+1,從fields[i]之后開(kāi)始比較 for (int j = i + 1; j < fields.length; j++) { Field fieldTmp = null; if (isSimpleType(fields[j].getType())) {// 與后面的第一個(gè)簡(jiǎn)單類型交互 fieldTmp = fields[i]; fields[i] = fields[j]; fields[j] = fieldTmp; break; // 后面的循環(huán),是沒(méi)有意義de } } } return fields; } /** * 這個(gè)方法是遞歸方法,并且并多個(gè)地方調(diào)用,考慮到循環(huán)引用和顯示格式, 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)); } }
不過(guò)呢上面代碼太繁瑣了,沒(méi)有考慮多種類型嵌套的問(wèn)題。
數(shù)組類型強(qiáng)轉(zhuǎn)會(huì)報(bào)ClassCastException 。
平常打日志就用log4j寫(xiě)個(gè)工具方法 比上面這個(gè)清晰明了多了。
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)); } }
相關(guān)文章
Go Java算法之K個(gè)重復(fù)字符最長(zhǎng)子串詳解
這篇文章主要為大家介紹了Go Java算法之K個(gè)重復(fù)字符最長(zhǎng)子串詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Java中args參數(shù)數(shù)組的用法說(shuō)明
這篇文章主要介紹了Java中args參數(shù)數(shù)組的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02Java的DelayQueue延遲隊(duì)列簡(jiǎn)單使用代碼實(shí)例
這篇文章主要介紹了Java的DelayQueue延遲隊(duì)列簡(jiǎn)單使用代碼實(shí)例,DelayQueue是一個(gè)延遲隊(duì)列,插入隊(duì)列的數(shù)據(jù)只有達(dá)到設(shè)置的延遲時(shí)間時(shí)才能被取出,否則線程會(huì)被阻塞,插入隊(duì)列的對(duì)象必須實(shí)現(xiàn)Delayed接口,需要的朋友可以參考下2023-12-12關(guān)于Unsupported major.minor version 49.0的錯(cuò)誤解決辦法
這篇文章主要介紹了關(guān)于Unsupported major.minor version 49.0的錯(cuò)誤解決辦法的相關(guān)資料,需要的朋友可以參考下2015-11-11java代碼規(guī)范之不合理命名與重復(fù)代碼示例詳解
這篇文章主要為大家介紹了java代碼規(guī)范之不合理命名與重復(fù)代碼示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Java 圖片與byte數(shù)組互相轉(zhuǎn)換實(shí)例
下面小編就為大家?guī)?lái)一篇Java 圖片與byte數(shù)組互相轉(zhuǎn)換實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02java高并發(fā)情況下高效的隨機(jī)數(shù)生成器
這篇文章主要介紹了java高并發(fā)情況下高效的隨機(jī)數(shù)生成器,對(duì)于性能有要求的同學(xué),可以參考下2021-04-04SpringBoot整合TomCat實(shí)現(xiàn)本地圖片服務(wù)器代碼解析
這篇文章主要介紹了SpringBoot整合TomCat實(shí)現(xiàn)本地圖片服務(wù)器代碼解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08