Java中Object.toString()返回的字符串的含义
toString()是Object类的一个公有方法,而所有类都继承自Object类。所以所有类即使不实现toString方法,也会存在从Object类继承来的toString。
类可以实现toString方法,在控制台中打印一个对象会自动调用对象类的toString方法,所以我们可以实现自己的toString方法在控制台中显示关于类的有用信息。
而八种基本数据类型没有toString()方法,只能使用相应的包装类才能使用toString()。
Object的toString方法返回的字符串很像是 对象名+@+对象内存地址,但事实并不是这样。
这里写了两段测试代码。
这两个方法大致是相同的,都会创建指定数量的元素,然后放入容器。
在添加的过程中如果出现重复则会打印出提示,执行完后会打印出统计信息。
第一个方法在对象上调用toString,将得到的字符串放入List
1 public static void list_obj_toString(int size) { 2 List<String> list = new ArrayList<>(); 3 int repeated = 0; 4 for (int i = 0; i < size; i++) { 5 Object obj = new Object(); 6 if (list.contains(obj.toString())) { 7 System.out.println("Object " + obj.toString() + " has repeated!"); 8 repeated++; 9 } else { 10 list.add(obj.toString()); 11 } 12 } 13 System.out.println("Total Object.toString():" + size); 14 System.out.println("Repeated Object.toString():" + repeated); 15 }
第二个方法直接将对象本身放入List
1 public static void list_obj(int size) { 2 List<Object> list = new ArrayList<>(); 3 int repeated = 0; 4 for (int i = 0; i < size; i++) { 5 Object obj = new Object(); 6 if (list.contains(obj)) { 7 System.out.println("Object " + obj.toString() + " has repeated!"); 8 repeated++; 9 } else { 10 list.add(obj); 11 } 12 } 13 System.out.println("Total Object:" + size); 14 System.out.println("Repeated Object:" + repeated); 15 }
public static void main(String[] args) { list_obj_toString(2000000); list_obj(2000000); }
在main中分别调用这两个方法,会得到结果
Object.toString() java.lang.Object@7f385cbe has repeated! Object.toString() java.lang.Object@26cfdc15 has repeated! ... ... Object.toString() java.lang.Object@f2eb847 has repeated! Object.toString() java.lang.Object@6f99ed9f has repeated! Total Object.toString():200000 Repeated Object.toString():8 Total Object:200000 Repeated Object:0
从结果看,对象的toString出现了8次重复,而对象的句柄(另一种说法是“对象的引用”)当然一次重复都没有。
问题出在哪里了呢?至少我们现在可以肯定“对象名+@+对象内存地址”这种说法肯定不对,因为内存地址肯定不会重复的。
先看看Java API文档,其中关于Object.toString()有这样一段描述
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '@' + Integer.toHexString(hashCode())
那么,原因就找到了。@后面的是转换为十六进制的对象的哈希值,所以当哈希冲突时,Object.toString()返回的字符串也不可避免地重复了。
以后再有人说toString会打印出对象的内存地址,你可以毫不犹豫地反驳他。
PS:当list_obj_toString的参数size为100000时,出现了0次重复。而参数为200000时,出现了8次重复。可见java 10的hashCode()的哈希算法在这个数量级上会开始出现大量的哈希冲突。