1. 概述
你有没有在调试时看到过类似 [Ljava.lang.Object;
这样的输出?看起来像乱码,其实它是 Java 虚拟机(JVM)内部对数组类型的表示方式。本文将带你搞清楚它的含义,并学会如何正确打印数组内容,避免踩坑。
2. Java 对象的默认 toString 行为
在 Java 中,如果你直接打印一个对象,底层会调用其 toString()
方法。对于数组这种特殊对象,默认的 toString()
并不会递归打印元素内容,而是返回一个包含类型信息的字符串。
来看个例子:
Object[] arrayOfObjects = { "John", 2, true };
assertTrue(arrayOfObjects.toString().startsWith("[Ljava.lang.Object;"));
✅ 这个测试会通过,但输出结果是 [Ljava.lang.Object;@7f31245a
这种形式,毫无可读性。
⚠️ 为什么是 [Ljava.lang.Object;
?
这是 JVM 内部使用的类型签名(Type Signature):
[
表示这是一个数组L
表示后面跟着的是一个类类型(Class Type)java.lang.Object;
是类的全限定名,分号;
是结束符
所以 [Ljava.lang.Object;
就代表 Object[]
类型。同理:
int[]
的内部表示是[I
String[]
是[Ljava.lang.String;
这也就是为什么直接打印数组得不到我们期望的结果。
3. 如何正确打印数组内容
想要获得可读性强的输出,不能依赖默认的 toString()
,得用更合适的方法。以下是几种推荐做法:
3.1 使用 Arrays 工具类 ✅
java.util.Arrays
提供了专门处理数组的工具方法,简单粗暴有效。
一维数组:Arrays.toString()
Object[] arrayOfObjects = { "John", 2, true };
assertEquals(Arrays.toString(arrayOfObjects), "[John, 2, true]");
多维数组:Arrays.deepToString()
如果数组中还嵌套了数组,必须用 deepToString
,否则内层数组仍会打印出 [Ljava...
。
Object[] innerArray = { "We", "Are", "Inside" };
Object[] arrayOfObjects = { "John", 2, innerArray };
assertEquals(Arrays.deepToString(arrayOfObjects), "[John, 2, [We, Are, Inside]]");
❌ 错误示范:
// 错!内层数组还是乱码
System.out.println(Arrays.toString(arrayOfObjects));
// 输出:[John, 2, [Ljava.lang.Object;@xxxxxx]
3.2 使用 Stream 流处理(JDK 8+)
Java 8 引入的 Stream API 也可以优雅地处理数组转换。
Object[] arrayOfObjects = { "John", 2, true };
List<String> listOfString = Stream.of(arrayOfObjects)
.map(Object::toString)
.collect(Collectors.toList());
assertEquals(listOfString.toString(), "[John, 2, true]");
这种方式灵活性更高,适合需要进一步处理的场景,比如过滤、格式化等。
4. 总结
[Ljava.lang.Object;
是 JVM 内部对Object[]
的类型表示,不是 bug,是规范- 直接打印数组会得到这种“看不懂”的字符串,因为
Object.toString()
不做深度遍历 - 正确做法:
- 一维数组 →
Arrays.toString()
- 多维/嵌套数组 →
Arrays.deepToString()
- 需要转换或处理 → 使用
Stream.of(array).map(...)
流式处理
- 一维数组 →
记住:调试时看到 [L
开头的字符串,第一时间反应应该是“哦,这是个数组,我得用 Arrays.deepToString()
”。
示例代码已托管至 GitHub:https://github.com/baeldung/java-core-tutorials