主要運用java反射原理,格式化輸出java對象屬性值,特別是list 和map。
MyTestUtil.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
|
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寫個工具方法 比上面這個清晰明了多了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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)); } } |