java反射原理制作對象打印工具
主要運用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,主要應(yīng)用java反射機制。 因為考慮到使用性和美觀性,沒有使用無限遞歸。
* 而是在toStr方法中加入一個boolean recursion ,是否遞歸。
* 當(dāng)然我們也可以將boolean recursion換成int recursion,控制遞歸次數(shù)。
* 其實就我使用經(jīng)驗來看,復(fù)雜數(shù)據(jù)toString,用json工具轉(zhuǎn)化成json輸出是一個不錯的方式。
//這是我用的方式,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方法,但是對象內(nè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是簡單類型的,復(fù)制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);// 設(shè)置些屬性是可以訪問的
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]是復(fù)雜類型
// 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; // 后面的循環(huán),是沒有意義de
}
}
}
return fields;
}
/**
* 這個方法是遞歸方法,并且并多個地方調(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));
}
}
不過呢上面代碼太繁瑣了,沒有考慮多種類型嵌套的問題。
數(shù)組類型強轉(zhuǎn)會報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));
}
}
相關(guān)文章
Java編程構(gòu)造方法與對象的創(chuàng)建詳解
這篇文章主要介紹了Java編程構(gòu)造方法與對象的創(chuàng)建詳解,具有一定參考價值,需要的朋友可以了解下。2017-11-11
解析MapStruct轉(zhuǎn)換javaBean時出現(xiàn)的詭異事件
在項目中用到了MapStruct,對其可以轉(zhuǎn)換JavaBean特別好奇,今天小編給大家分享一個demo給大家講解MapStruct轉(zhuǎn)換javaBean時出現(xiàn)的詭異事件,感興趣的朋友一起看看吧2021-09-09
Java?將HTML轉(zhuǎn)為XML的詳細(xì)步驟
這篇文章主要介紹了Java?將HTML轉(zhuǎn)為XML,本文將以html轉(zhuǎn)為xml格式為例,介紹如何實現(xiàn)轉(zhuǎn)換,以下是詳細(xì)方法及步驟,需要的朋友可以參考下2022-06-06
spring/springboot整合dubbo詳細(xì)教程
今天教大家如何使用spring/springboot整合dubbo,文中有非常詳細(xì)的圖文介紹及代碼示例,對正在學(xué)習(xí)java的小伙伴有很好地幫助,需要的朋友可以參考下2021-05-05
mybatis報錯元素內(nèi)容必須由格式正確的字符數(shù)據(jù)或標(biāo)記組成異常的解決辦法
今天小編就為大家分享一篇關(guān)于mybatis查詢出錯解決辦法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12
spring mvc+localResizeIMG實現(xiàn)HTML5端圖片壓縮上傳
這篇文章主要為大家詳細(xì)介紹了使用spring mvc+localResizeIMG實現(xiàn)HTML5端圖片壓縮上傳,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04

