概述
上一节总结了Java反射机制里涉及到的几个类和其用法,本节就应用这些类和方法实现一个通用的toString()方法。
要将一个对象toString,我们需要考虑到哪些方面呢?
1. 如果对象是一个数组,那么我们需要遍历其元素,然后将元素作为新的对象递归调用我们的toString方法;
2. 如果对象是个基本类型/字符串,那么可以直接返回其value;
3. 如果对象是个复杂对象,那么我们需要获取其所有的字段,然后遍历,如果该字段是基本类型/字符串,则直接返回其value,否则将每个字段作为新的对象递归调用我们的toString方法;
4. 不处理Map对象,因为其实现类都实现了toString方法。
实现如下:
package reflect;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
/**
* @author rambo.pan
* 2016年10月10日
*/
public class ObjectAnalyzer {
private static final String NULL_STRING = "null";
private static final String VISITED_STRING = "...";
//该数组用来记录已解析过的对象类型
private List<Object> visited = new ArrayList<Object>();
/**
* 递归方法,object是个数组,则遍历其元素,递归调用该方法;否则是个类实例,则遍历其所有字段
* @param obj
* @return
*/
public String toString(Object obj){
//如果对象为空,则返回null
if (obj == null) {
return NULL_STRING;
}
//如果对象已被处理过,则返回,针对于 A、B对象相互组合的情况,否则会循环递归,导致StackOverFlow
if (visited.contains(obj)) {
return VISITED_STRING;
}
visited.add(obj);
//获取对象的Class实例,同一个类的对象,共有一个相应的Class实例,在类被加载到虚拟机时就存储在方法区中了
Class<?> cl = obj.getClass();
//如果对象正好是String对象,则强转后直接返回
if (cl == String.class) {
return (String)obj;
}
//如果object是个数组,则遍历其元素,对元素进行toString(Object)递归调用
if (cl.isArray()) {
//获取数组的元素类型
String r = cl.getComponentType() + "[]{";
for (int i = 0; i < Array.getLength(obj); i++) {
if (i > 0) {
r += ",";
}
//获取指定下标的数组元素
Object val = Array.get(obj, i);
//如果元素是原始/基本类型(Java共8种基本类型),则直接输出
if (cl.getComponentType().isPrimitive()) {
r += val;
}else {//否则递归调用,直到其为原始类型
r += toString(val);
}
}
//对数组元素遍历完成,返回。
return r + "}";
}
//object不是数组类型,首先获取其类型Name
String r = cl.getName();
//遍历object的所有字段,然后获取字段的Name和Value,之后再遍历其父类,直到遍历到父类为Object
do{
r += "[";
//获取object的所有字段,无论访问限制符是public还是private,但不包括其从父类继承来的字段
Field[] fields = cl.getDeclaredFields();
//设置字段的访问权限为可访问
AccessibleObject.setAccessible(fields, true);
for (Field field : fields) {
//忽略static属性
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (!r.endsWith("[")) {
r += ",";
}
r += field.getName() + "=";
try{
//获取字段类型和字段的值
Class<?> t = field.getType();
Object val = field.get(obj);
//如果字段类型是原始类型,则直接输出;否则递归调用toString(Object)
if (t.isPrimitive()) {
r += val;
}else {
r += toString(val);
}
}catch (Exception e) {
e.printStackTrace();
}
}
//一个类型的字段遍历结束
r += "]";
//获取该类型的父类Class实例,然后继续该循环
cl = cl.getSuperclass();
}while(cl != null);
//类型遍历完成,返回object的字符串结果
return r;
}
}
最后
以上就是苗条小懒虫为你收集整理的反射应用之一---编写通用的toString()方法的全部内容,希望文章能够帮你解决反射应用之一---编写通用的toString()方法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复