Arrays中的toString和deepToString

说明

在某些情况下,我们需要将数组显示或打印出来,部分情况下,我们可以借用JSON或者XML工具类将数组打印出来,但Java本身提供了数组打印的方法,由于本身记忆力不深,所以记录一下

Arrays.toString

源码

public static String toString(Object[] a) {
    if (a == null)
        return "null";

    int iMax = a.length - 1;
    if (iMax == -1)
        return "[]";

    StringBuilder b = new StringBuilder();
    b.append('[');
    for (int i = 0; ; i++) {
        b.append(String.valueOf(a[i]));
        if (i == iMax)
            return b.append(']').toString();
        b.append(", ");
    }
}

解析

  1. 可以看到,Arrays.toString方法在传输对象是空的情况下,直接返回null字符串(并非是空字符串,这个经常出现错误);
  2. 在数组长度是0的时候,直接返回“[]”;
  3. 整体是使用StringBuilder实现拼接,放入的内容也是String.valueOf的内容(不放toString的原因是因为可能会产生NPE异常);
  4. 至于为什么iMax要用数组长度-1,也是为了后面的循环中方便判断如果是最后一位,则不加逗号。

结语

这种情况下,一维数组是完全没有问题的,但是如果是二维数据则可能出现问题,例如一个二维int数组,则会直接返回如下的类似结果:
[[I@66cd51c3, [I@4dcbadb4, [I@4e515669]
这种情况下应当使用同类下的deepToString方法

Arrays.deepToString

源码

public static String deepToString(Object[] a) {
    if (a == null)
        return "null";

    int bufLen = 20 * a.length;
    if (a.length != 0 && bufLen <= 0)
        bufLen = Integer.MAX_VALUE;
    StringBuilder buf = new StringBuilder(bufLen);
    deepToString(a, buf, new HashSet<Object[]>());
    return buf.toString();
}

private static void deepToString(Object[] a, StringBuilder buf,
                                    Set<Object[]> dejaVu) {
       if (a == null) {
           buf.append("null");
           return;
       }
       int iMax = a.length - 1;
       if (iMax == -1) {
           buf.append("[]");
           return;
       }

       dejaVu.add(a);
       buf.append('[');
       for (int i = 0; ; i++) {

           Object element = a[i];
           if (element == null) {
               buf.append("null");
           } else {
               Class<?> eClass = element.getClass();

               if (eClass.isArray()) {
                   if (eClass == byte[].class)
                       buf.append(toString((byte[]) element));
                   else if (eClass == short[].class)
                       buf.append(toString((short[]) element));
                   else if (eClass == int[].class)
                       buf.append(toString((int[]) element));
                   else if (eClass == long[].class)
                       buf.append(toString((long[]) element));
                   else if (eClass == char[].class)
                       buf.append(toString((char[]) element));
                   else if (eClass == float[].class)
                       buf.append(toString((float[]) element));
                   else if (eClass == double[].class)
                       buf.append(toString((double[]) element));
                   else if (eClass == boolean[].class)
                       buf.append(toString((boolean[]) element));
                   else { // element is an array of object references
                       if (dejaVu.contains(element))
                           buf.append("[...]");
                       else
                           deepToString((Object[])element, buf, dejaVu);
                   }
               } else {  // element is non-null and not an array
                   buf.append(element.toString());
               }
           }
           if (i == iMax)
               break;
           buf.append(", ");
       }
       buf.append(']');
       dejaVu.remove(a);
   }

解析

  1. 方法内第四行设置bufLen的原因是为了减少StringBuilder的扩增次数(StringBuilder的原理不做扩展);
  2. 随后直接调用内部方法deepToString进行写入;
  3. 可以看到,deepToString内部方法中,如果当前层不是数组,直接使用toString方法,如果是基本数组,那么直接像toString那样append,如果不是基本数组,则循环调用当前方法;
  4. 值得关注的一个坑点是很容易注意到在deepToString内部方法中,有一个dejaVu变量,这个变量是用于检测当前是否有循环引用,就是当元素本身是自己的时候,将会返回"[…]",这个地方展开说下,什么情况下会产生这个情况呢,举个例子:
Object[] group1 = new Object[1];
group1[0] = group1;
String b = Arrays.deepToString(group1);
这个时候b的值就是“[[...]]”,但是注意,代码中一些成员属性引用自身的情况是无法检测出来的,例如如下代码:
@ToString
@Builder
@Data
static class Student{
    private String name;
    private Integer age;
    private Student[] student;
}

public static void main(String[] args) {
    Student[] group1 = {Student.builder().name("tim").age(18).build(),Student.builder().name("bob").age(19).build()};
    group1[0].setStudent(group1);
    String b = Arrays.deepToString(group1);
}
如果这样写,会导致StackOverflowError,是一个需要注意的地方(和JSON相关的工具类产生的结果保持一致)。

结语

在一般的情况下,可以更多的使用deepToString来进行数组输出,毕竟有些情况下是没有第三方工具包

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值