## 打印数组

“哥，之前听你说，数组也是一个对象，但 Java 中并未明确的定义这样一个类。”看来三妹有在用心地学习。

“是的，因此数组也就没有机会覆盖 `Object.toString()` 方法。如果尝试直接打印数组的话，输出的结果并不是我们预期的结果。”我接着三妹的话继续说。

“那怎么打印数组呢？”三妹心有灵犀地把今天的核心问题提了出来。

“首先，我们来看一下，为什么不能直接打印数组，直接打印的话，会出现什么问题。”

来看这样一个例子。

```
String [] cmowers = {"沉默","王二","一枚有趣的程序员"};
System.out.println(cmowers);
```

程序打印的结果是：

```
[Ljava.lang.String;@3d075dc0
```

`[Ljava.lang.String;` 表示字符串数组的 Class 名，@ 后面的是十六进制的 hashCode——这样的打印结果太“人性化”了，一般人表示看不懂！为什么会这样显示呢？查看一下 `java.lang.Object` 类的 `toString()` 方法就明白了。

```java
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
```

再次证明，数组虽然没有显式定义成一个类，但它的确是一个对象，继承了祖先类 Object 的所有方法。

“哥，那为什么数组不单独定义一个类来表示呢？就像字符串 String 类那样呢？”三妹这个问题让人头大，但也好解释。

“一个合理的说法是 Java 将其隐藏了。假如真的存在这么一个类，就叫 Array.java 吧，我们假想一下它真实的样子，必须得有一个容器来存放数组的每一个元素，就像 String 类那样。”一边回答三妹，我一边打开了 String 类的源码。

```java
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
}
```

“最终还是要用类似一种数组的形式来存放数组的元素，对吧？这就变得很没有必要了，不妨就把数组当做是一个没有形体的对象吧！”

“好了，不讨论这个了。”我怕话题扯远了，扯到我自己也答不出来就尴尬了，赶紧把三妹的思路拽了回来。

“我们来看第一种打印数组的方法，使用时髦一点的 Stream 流。”

第一种形式：

```java
Arrays.asList(cmowers).stream().forEach(s -> System.out.println(s));
```

第二种形式：

```java
Stream.of(cmowers).forEach(System.out::println);
```

第三种形式：

```java
Arrays.stream(cmowers).forEach(System.out::println);
```

打印的结果如下所示。

```
沉默
王二
一枚有趣的程序员
```

没错，这三种方式都可以轻松胜任本职工作，并且显得有点高大上，毕竟用到了 Stream，以及 lambda 表达式。

“当然了，也可以使用比较土的方式，for 循环。甚至 for-each 也行。”

```java
for(int i = 0; i < cmowers.length; i++){
    System.out.println(cmowers[i]);
}

for (String s : cmowers) {
    System.out.println(s);
}
```

“哥，你难道忘了[上一篇](https://mp.weixin.qq.com/s/acnDNH6A8USm_EYIT6i-jA)在讲 Arrays 工具类的时候，提到过另外一种方法 `Arrays.toString()` 吗？”三妹看我一直说不到点子上，有点着急了。

“当然没有了，我认为 `Arrays.toString()` 是打印数组的最佳方式，没有之一。”我的情绪有点激动。

`Arrays.toString()` 可以将任意类型的数组转成字符串，包括基本类型数组和引用类型数组。该方法有多种重载形式。

![](https://cdn.jsdelivr.net/gh/itwanger/jmx-java/images/array/print-01.png)

使用 `Arrays.toString()` 方法来打印数组再优雅不过了，就像，就像，就像蒙娜丽莎的微笑。

![](https://cdn.jsdelivr.net/gh/itwanger/jmx-java/images/array/print-02.png)

（三妹看到这么一副图的时候忍不住地笑了）

“三妹，你不要笑，来，怀揣着愉快的心情看一下代码示例。”

```java
String [] cmowers = {"沉默","王二","一枚有趣的程序员"};
System.out.println(Arrays.toString(cmowers));
```

程序打印结果：

```
[沉默, 王二, 一枚有趣的程序员]
```

哇，打印格式不要太完美，不多不少！完全是我们预期的结果：`[]` 表明是一个数组，`,` 点和空格用来分割元素。

“哥，那如果我想打印二维数组呢？”

“可以使用 `Arrays.deepToString()` 方法。”

```java
String[][] deepArray = new String[][] {{"沉默", "王二"}, {"一枚有趣的程序员"}};
System.out.println(Arrays.deepToString(deepArray));
```

打印结果如下所示。

```
[[沉默, 王二], [一枚有趣的程序员]]
```

-------

“说到打印，三妹，哥给你提醒一点。阿里巴巴的 Java 开发手册上有这样一条规约，你看。”

![](https://cdn.jsdelivr.net/gh/itwanger/jmx-java/images/array/print-03.png)

“什么是 POJO 呢，就是 Plain Ordinary Java Object 的缩写，一般在 Web 应用程序中建立一个数据库的映射对象时，我们称它为 POJO，这类对象不继承或不实现任何其它 Java 框架的类或接口。”

“对于这样的类，最好是重写一下它的 `toString()` 方法，方便查看这个对象到底包含了什么字段，好排查问题。”

“如果不重写的话，打印出来的 Java 对象就像直接打印数组的那样，一串谁也看不懂的字符序列。”

“可以借助 Intellij IDEA 生成重写的  `toString()` 方法，特别方便。”

“好的，哥，我记住了。以后遇到的话，我注意下。你去休息吧，我来敲一下你提到的这些代码，练一练。”

“OK，我走，我走。”

-----

《**教妹学 Java**》预计一个月左右会有一次内容更新和完善，大家在我的公众号 **沉默王二** 后台回复“**03**” 即可获取最新版！如果觉得内容不错的话，欢迎转发分享！

<img src="https://cdn.jsdelivr.net/gh/itwanger/jmx-java/images/itwanger.png" alt="图片没显示的话，可以微信搜索「沉默王二」关注" style="zoom:50%;" />
