java反射原理制作对象打印工具
主要运用java反射原理,格式化输出java对象属性值,特别是list和map。
MyTestUtil.java
packageutils;
importjava.lang.reflect.Field;
importjava.text.SimpleDateFormat;
importjava.util.Arrays;
importjava.util.Collection;
importjava.util.Date;
importjava.util.Iterator;
importjava.util.Map;
importjava.util.Map.Entry;
/**
*这个类是方便控制台输出object,主要应用java反射机制。因为考虑到使用性和美观性,没有使用无限递归。
*而是在toStr方法中加入一个booleanrecursion,是否递归。
*当然我们也可以将booleanrecursion换成intrecursion,控制递归次数。
*其实就我使用经验来看,复杂数据toString,用json工具转化成json输出是一个不错的方式。
//这是我用的方式,booleanrecursion是否递归
publicstaticintadd(inti,booleanrecursion){
sum+=i;
if(recursion)
add(i,false);
returnsum;
}
//也可以这样,intrecursion表示递归次数
publicstaticintadd(inti,intrecursion){
sum+=i;
if(recursion>0){
recursion--;
add(i,recursion);
}
returnsum;
}
*
*
*@authorklguang
*
*/
publicclassMyTestUtil{
staticfinalStringSPLIT_LINE="=";//分割线
staticfinalStringMY_SIGN="KLG_print";//默認標記
privatestaticStringDATE_FORMAT="yyyy-MM-ddHH:mm:ss";
/**
*将集合类型toSring方法
*@paramobject
*@paramrecursion
*是否递归
*@return
*/
privatestaticStringcollectionToStr(Objectobject,booleanrecursion){
if(object==null)
return"null";
Object[]a=null;
//将集合类型转换成数组类型
if(isArrayType(object))
a=(Object[])object;
else
a=((Collection)object).toArray();
if(isSimpleArr(a)||!recursion)
returnArrays.toString(a);
else
returncomplexArrToStr(a);
}
/**
*Arrays有toString方法,但是对象内容太多,在一行显示还有就是没有显示index信息
*/
privatestaticStringcomplexArrToStr(Object[]a){
if(a==null)
return"null";
intiMax=a.length-1;
if(iMax==-1)
return"[]";
StringBuilderb=newStringBuilder();
for(inti=0;;i++){
Stringvalue=objToStr(a[i],false);
b.append("["+i+"]"+"->"+value);
if(i==iMax)
returnb.toString();
b.append(",\r\n");
}
}
/**
*map类型toString方法
*
*@parammap
*@paramrecursion
*是否递归
*@return
*/
privatestaticStringmapToStr(Map<String,Object>map,booleanrecursion){
if(map==null)
return"null";
if(isSimpleMap(map)||!recursion)
returnsimpleMapToStr(map);
else
returncomplexMapToStr(map,true);
}
/**
*map的value是简单类型的,复制Map.toString,我给它加了换行10个换行
*
*@parammap
*@return
*/
privatestaticStringsimpleMapToStr(Mapmap){
Iterator<Entry<String,Object>>i=map.entrySet().iterator();
if(!i.hasNext())
return"{}";
StringBuildersb=newStringBuilder();
sb.append('{');
for(intt=1;;t++){
Entry<String,Object>e=i.next();
sb.append(e.getKey()).append("=").append(e.getValue());
if(!i.hasNext())
returnsb.append('}').toString();
sb.append(',').append('');
if(t%10==0&&t!=0)
sb.append("\r\n");
}
}
privatestaticStringcomplexMapToStr(Mapmap,booleanrecursion){
Iterator<Entry<String,Object>>i=map.entrySet().iterator();
if(!i.hasNext())
return"{}";
StringBuildersb=newStringBuilder();
sb.append("{\r\n");
for(intt=1;;t++){
Entry<String,Object>e=i.next();
Stringkey=String.valueOf(e.getKey());
Objectvalue=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())
returnsb.append("\r\n}").toString();
sb.append(',').append("\r\n");
}
}
/**
*
*
*@paramobject
*@paramrecursion
*是否要递归
*@return
*/
privatestaticStringbeanToStr(Objectobject,booleanrecursion){
if(object==null)
return"null";
Classclazz=object.getClass();
StringBuildersb=newStringBuilder();
//返回源代码中给出的底层类的简称
sb.append(clazz.getSimpleName()).append("[");
Field[]fields=sortFieldByType(clazz.getDeclaredFields());
intiMax=fields.length-1;
if(iMax==-1)
returnsb.append("]").toString();
for(inti=0;;i++){
Fieldfield=fields[i];
field.setAccessible(true);//设置些属性是可以访问的
Stringname=field.getName();//取得field的名称
if(name.equals("serialVersionUID"))
continue;
try{
Objectvalue=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(Exceptione){
e.printStackTrace();
}
if(i==iMax)
returnsb.append("]").toString();
sb.append(",");
}
}
privatestaticStringindent(intlength,Stringsign){
StringBuildersb=newStringBuilder();
for(inti=0;i<length;i++){
sb.append(sign);
}
returnsb.toString();
}
privatestaticbooleanisSimpleType(Objectobj){
if(obj==null)
returntrue;
else{
ClassobjectClass=obj.getClass();
returnisSimpleType(objectClass);
}
}
/**
*
*@paramobjectClass
*用obj.getClass()取得
*@return
*/
privatestaticbooleanisSimpleType(ClassobjectClass){
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){
returntrue;
}else{
returnfalse;
}
}
/**
*MethodisCollectionType
*
*@paramobj
*Object
*@returnboolean
*/
privatestaticbooleanisCollectionType(Objectobj){
if(obj==null)
returnfalse;
return(obj.getClass().isArray()||(objinstanceofCollection));
}
privatestaticbooleanisArrayType(Objectobj){
if(obj==null)
returnfalse;
return(obj.getClass().isArray());
}
privatestaticbooleanisMapType(Objectobj){
if(obj==null)
returnfalse;
return(objinstanceofMap);
}
privatestaticbooleanisDateType(Objectobj){
if(obj==null)
returnfalse;
return(objinstanceofDate);
}
privatestaticbooleanisBeanType(Objectobj){
if(isSimpleType(obj)||isCollectionType(obj)||isMapType(obj))
returnfalse;
else
returntrue;
}
privatestaticbooleanisSimpleArr(Object[]a){
if(a==null||a.length<1)
returntrue;
booleanflag=true;
for(Objecto:a){
if(!isSimpleType(o)){
flag=false;
break;
}
}
returnflag;
}
privatestaticbooleanisSimpleMap(Mapmap){
if(map==null)
returntrue;
Iterator<Entry<String,Object>>i=map.entrySet().iterator();
booleanflag=true;
while(i.hasNext()){
Entry<String,Object>e=i.next();
if(!isSimpleType(e.getValue())){
flag=false;
break;
}
}
returnflag;
}
/***
*将简单类型排在前面
*@paramfields
*@return
*/
publicstaticField[]sortFieldByType(Field[]fields){
for(inti=0;i<fields.length;i++){
if(isSimpleType(fields[i].getType()))
continue;//fields[i]是简单类型不管
//fields[i]是复杂类型
//intj=i+1,从fields[i]之后开始比较
for(intj=i+1;j<fields.length;j++){
FieldfieldTmp=null;
if(isSimpleType(fields[j].getType())){//与后面的第一个简单类型交互
fieldTmp=fields[i];
fields[i]=fields[j];
fields[j]=fieldTmp;
break;//后面的循环,是没有意义de
}
}
}
returnfields;
}
/**
*这个方法是递归方法,并且并多个地方调用,考虑到循环引用和显示格式,booleanrecursion取得确保递归可以被终止。
*
*@paramobject
*@paramrecursion
*是否需要更深一层显示
*@return
*/
privatestaticStringobjToStr(Objectobject,booleanrecursion){
if(object==null)
return"null";
object.toString();
if(isDateType(object))
returnnewSimpleDateFormat(DATE_FORMAT).format((Date)object);
elseif(isBeanType(object))
returnbeanToStr(object,recursion);
elseif(isCollectionType(object))
returncollectionToStr(object,recursion);
elseif(isMapType(object))
returnmapToStr((Map)object,recursion);
else
returnString.valueOf(object);
}
publicstaticStringobjToStr(Objectobj){
returnobjToStr(obj,true);
}
privatestaticvoidprint(Objectobj,Stringsign,Stringcontent){
Stringbegin=indent(15,SPLIT_LINE)+""+obj.getClass().getSimpleName()
+">>"+sign+""+indent(10,SPLIT_LINE);
intlength=(begin.length()-sign.length()-5)/2;
Stringend=indent(length,SPLIT_LINE)+""+sign+""+indent(length,SPLIT_LINE);
System.out.println(begin+"\r\n"+content+"\r\n"+end);
}
publicstaticvoidprint(Objectobj){
print(obj,MY_SIGN,objToStr(obj));
}
publicstaticvoidprintWithSign(Stringsign,Objectobj){
print(obj,sign,objToStr(obj));
}
}
不过呢上面代码太繁琐了,没有考虑多种类型嵌套的问题。
数组类型强转会报ClassCastException。
平常打日志就用log4j写个工具方法比上面这个清晰明了多了。
publicstaticvoiddebug(Stringmessage,Objecto){
intcount=0;
if(o==null){
LOGGER.debug(chain(message,":null"));
return;
}
if(o.getClass().isArray()){
for(inti=0,len=Array.getLength(o);i<len;i++){
debug(chain(message,"-[",i,"]"),Array.get(o,i));
}
}elseif(oinstanceofMap){
Entry<?,?>e;
for(Iterator<?>it=((Map<?,?>)o).entrySet().iterator();it.hasNext();){
e=(Entry<?,?>)it.next();
debug(chain(message,"-[K:",e.getKey(),"]"),e.getValue());
}
}elseif(oinstanceofIterable){
for(Iterator<?>it=((Iterable<?>)o).iterator();it.hasNext();){
count++;
debug(chain(message,"-[",count,"]"),it.next());
}
}else{
LOGGER.debug(chain(message,":",o));
}
}