Java中为何打印ArrayList实例输出实际值而非内存地址?附数组对比示例
输出差异的核心原因
这一现象和“值存储/引用存储”的规则毫无关联,核心逻辑来自System.out.println()的统一实现:
当你向println()传入任意引用类型对象时,方法内部最终会调用该对象的toString()方法,拿到返回的字符串后再输出。你最终看到的打印内容,完全由toString()方法的实现决定,和对象是值存还是引用存没有任何关系。
为什么数组打印是类似内存地址的格式
Java的数组是特殊的引用类型,但所有数组类型都没有重写Object类自带的toString()方法。
Object类原生的toString()实现逻辑是拼接「对象类名@对象的身份哈希值」,这个字符串的排版看起来类似内存地址,实际上并不是真实的JVM内存地址,只是用来标识对象身份的哈希值。
所以你直接打印数组a时,走的就是这套原生逻辑,输出类似[Ljava.lang.Object;@74a14482的内容,也就是你误以为的“内存地址”。
为什么ArrayList打印是实际存储内容
ArrayList在源码中从一开始就重写了toString()方法。
它的toString()实现完全没有沿用Object的原生逻辑,而是遍历内部维护的元素数组,把所有元素按顺序拼接成[元素1, 元素2, ...]格式的字符串返回。这套实现是Java集合类的通用设计,所以你打印ArrayList实例b时,看到的就是[3, 4]这样的实际内容。
常见认知纠偏
- 从来不存在“引用类型打印必出内存地址”的规则,判断打印结果的唯一标准就是对应类有没有重写
toString():- 日常用到的String、Integer、HashMap、HashSet等类,全都重写了
toString()方法,打印时都会输出自身的内容信息,不会出现类名@哈希值的格式; - 如果你自定义一个普通的业务类,不做任何方法重写,直接实例化后打印,输出才会是类名@哈希值的格式;
- 哪怕你给自定义类的
toString()随便返回一句固定文本,打印时也只会看到这句文本,和对象的存储位置、存储方式完全无关。
- 日常用到的String、Integer、HashMap、HashSet等类,全都重写了
内容的提问来源于stack exchange,提问作者John Kang
相关产品推荐
相关产品推荐

