反射应用 - toString方法/泛型数组代码
我们常用的toString方法都是显式地调用其域,当需要时,要在类中重写toString方法(基本上一个类一个),而通用toString方法什么都不需要知道,直接调用即可。
泛型数组代码不需要记,是java.util.Arrays类中copyOf(T[] original, int newLength) 方法实现底层中使用了反射机制,这里介绍了一下而已。
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
public class ObjectAnalyzer{
private ArrayList<Object> vistied =new ArrayList<>();
public String toString(Object obj) {
if (obj == null) return "null"; //对象为null,返回“null”
if (vistied.contains(obj)) return "..."; //
vistied.add(obj);
Class<? extends Object> c1 = obj.getClass();
if(c1 == String.class) return (String) obj; //对象类型为字符串,直接打印
//对象类型为数组
if(c1.isArray()) {
String r = c1.getComponentType() + "[]{"; //getComponentType返回数组类型
for(int i=0;i<Array.getLength(obj);i++) { //getLength返回数组长度
if(i>0) r +=","; //逗号分隔元素
Object val =Array.get(obj, i); //返回数组中指定索引的值
if(c1.getComponentType().isPrimitive()) //若数组中类型为基本类型,直接添加于字符串r中
r += val;
else
r += toString(val); //递归,执行本方法中‘对象类型非数组’部分
}
return r+"}";
}
//对象类型为非数组
String r = c1.getName(); //获取对象所属的类
do {
r += "[";
Field[] fields = c1.getDeclaredFields(); //获取本类所有域
AccessibleObject.setAccessible(fields, true); //开放域的访问限制
for(Field f: fields) {
if(!Modifier.isStatic(f.getModifiers())) { //非静态域
if(!r.endsWith("[")) r += ",";
r += f.getName() + "=";
try { //处理异常
Class<?> t = f.getType(); //获取域的类型
Object val = f.get(obj); //获取域值
if(t.isPrimitive())
r+= val; //若域类型为基本数据类型,直接加入域值
else
r += toString(val); //若域类型为对象,调用本方法
}catch(Exception e){
e.printStackTrace();
}
}
}
r += "]";
c1 = c1.getSuperclass(); //开始获取超类的域
}while(c1 != null);
return r;
}
//泛型数组代码
public static Object copyOf(Object a,int newLength) { //参数类型定义为Object,而不可以是Object[],是因为基本类型数组不可转换为Object[],但可以是Object
Class<? extends Object> c1 = a.getClass();
if(!c1.isArray()) return null; //不是数组,返回null
Class<?> componentType = c1.getComponentType(); //获取数组类型
int length = Array.getLength(a); //获取数组长度
Object newArray = Array.newInstance(componentType, newLength);
System.arraycopy(a, 0, newArray, 0, Math.min(length,newLength));
return newArray;
}
}
//调用toString方法
Employee em = new Employee(2,3,4,5);
System.out.println(new ObjectAnalyzer().toString(em));
返回类型 | 方法名和参数 | 解释 |
---|---|---|
static Object | get(Object array, int index) | 返回存储在指定index上给定数组的内容 |
static xxxx | getXxxx(Object array, int index) | 若index索引处的类型为基本类型,可直接调用相关方法,那样得到的结果就不用强转了 |
static void | set(Object array, int index, Object value) | 将新值存储到给定位置上的给定数组中 |
static void | setXxxx(Object array, int index, Object value) | 若index索引处的类型为基本类型,可直接调用相关方法 |
static int | getLength(Object array) | 返回指定数组对象的长度 |
static Object | newInstance(Class<?> componentType, int length) | 返回具有给定类型,给定长度的新数组 |