几乎每个Java初学者都真实踩过一次这个坑——直接println一个数组,得到一串看不懂的乱码。这篇真实拆解这串"乱码"到底是什么、每个字符代表什么,以及不同类型数组的前缀真实有什么规律。
直接对一个int[]数组调用println(),看真实输出的每一部分代表什么。
ArrayToStringPitfallDemo.java int[] arr = {1, 2, 3}; System.out.println(arr);
直接打印int[]数组真实输出: [I@7ad041f3 arr.toString() 真实结果: [I@7ad041f3 字符串真实是否以[I@开头: true
真实结果证明了数组没有重写 Object.toString(),所以打印出来的真实是默认格式:getClass().getName() + "@" + Integer.toHexString(hashCode())。[I 是 JVM 内部对数组类型的命名规则——[ 代表"这是一个数组"(一维数组一个方括号),I 是 int 的类型代号(取自 Integer 的首字母),@ 后面真实是这个数组对象的 identity hashCode 的十六进制表示——和内容完全没有关系,纯粹是一个身份标识。
int有专属代号I,那其他基本类型和引用类型呢?
double[] 真实toString前缀: [D(D代表double) String[] 真实toString前缀: [L(L代表引用类型,后面真实跟着完整类名) long[] 真实toString前缀: [J(J代表long,因为L已经被引用类型占用) String[] 真实完整toString: [Ljava.lang.String;@7852e922 int[][] 真实toString前缀: [[I(多一个[代表多一维)
Arrays.toString(arr) 真实结果: [1, 2, 3] Arrays.deepToString(arr2d) 真实结果: [[1, 2], [3, 4]] 直接打印List真实结果: [[I@5c647e05](每个元素依然是[I@形式,不是内容)
真实结果验证了正确姿势:一维数组用 Arrays.toString(),多维数组用 Arrays.deepToString()——它们内部会真实递归遍历数组元素并拼出可读的内容。最后一个真实结果特别值得注意:即使把数组放进一个 List 再整体打印,List.toString() 内部对每个元素调用的依然是元素自己的 toString(),数组元素同样真实没有重写这个方法,陷阱一样会出现——这也是这个坑在真实项目里最容易反复中招的地方:开发者以为用了集合包装就"安全"了,实际上数组本身的问题没有解决。
每一行都是真实运行这段代码得到的结果。