前段时间写bantouyan-json代码,偶然发现Java集合类的一个问题,就是一旦集合中出现了循环引用,调用hashCode方法就会触发StackOverflowError错误。一般情况下集合内不会出现循环引用,但Java集合并不禁止这样做,从具体应用上讲,循环引用的情况也有可能出现。但是,一旦直接或间接调用hashCode方法,就会导致StackOverflowError,我不清楚Java这样设计是一个失误还是这种情况没有必要处理,但它的存在会给代码设计带来一定的问题。
我当时的情况是想用HashSet存储一个ArraList对象,代码是这样写的:
ArrayList<Object> list = new ArrayList<Object>();
list.add(list);
HashSet<Object> set = new HashSet<Object>();
set.add(list);
//Exception in thread "main" java.lang.StackOverflowError
// at java.util.AbstractList$Itr.next(AbstractList.java:345)
// at java.util.AbstractList.hashCode(AbstractList.java:526)
// at java.util.AbstractList.hashCode(AbstractList.java:527)
结果测试时就冒出了StackOverflowError错误,是由于间接调用AbstractList的hashCode方法引起的。查看Java的API文档,AbstractList的hashCode是把每一个子元素的hashCode经过迭代计算得到的,也就是说,要计算AbstractList的hashCode,就要把每一个子元素的hashCode先计算一遍,如果这些子元素中的某一个或子元素的子元素引用到上级对象,那么hashCode方法就会出现无限递归调用,最终出现StackOverflowError错误。
经检查,不光是List,其他集合对象,如Map、Set、Stack等也有这个问题,即他们的hashCode也是通过计算子元素的hashCode得到的。也就是说,无论是List,还是Map、Set,只要内部出现了循环引用,如一个List引用了一个Map,Map又引用了顶层的List,调用hashCode方法就会导致堆栈溢出错误。
这种错误出现的几率非常低,但存在这样的问题不能不说是Java集合设计的一个失误。既然应用中有可能出现集合间的循环引用,就应该避免这种错误出现。
分享到:
相关推荐
实际上,hashcode根本不能代表object的内存地址。
Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.
解析Java对象的equals()和hashCode()的使用
主要给大家介绍了关于Java中HashCode方法的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
java中Hashcode的作用
注意:因为Person类是自定义类,需要重写hashCode()方法和equals()方法,并规定只有姓名和身份证号都相等,则对象相等。 其中计算哈希码的算法:(31 + ((name == null) ? 0 : name.hashCode()))*31 + id (注:...
如何正确实现Java中的HashCode共6页.pdf.zip
主要介绍了java 中HashCode重复的可能性的相关资料,这里提供实例及测试代码,需要的朋友可以参考下
本文介绍了Java语言不直接支持关联数组,可以使用任何对象作为一个索引的数组,但在根Object类中使用 hashCode()方法明确表示期望广泛使用HashMap。理想情况下基于散列的容器提供有效插入和有效检索;直接在对象模式...
Java基础加强_ArrayList_HashSet的比较及Hashcode分析
知道如何在特定的条件下选择适合的集合类/接口。 能正确地实现hashcode方法。
本篇文章主要介绍了Java中的hashcode方法,详细的介绍了hashCode方法的作用,具有一定的参考价值,有需要的可以了解一下。
在Java的Object类中有一个方法: public native int hashCode(); 根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现。 为何Object类需要这样一...
NULL 博文链接:https://songjianyong.iteye.com/blog/1676894
总结非常完全的文档。对Java初学着和进阶学习的学者是一份相当不错的Java学习资料
java 序列化和重写 hashCode 以及 equals 方法的例子
NULL 博文链接:https://zpointer.iteye.com/blog/1058337
有许多人学了很长时间的Java,但一直不明白hashCode方法的作用以及equals()和==的区别,我来解释一下吧。...总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。你知道它们的区别吗?
一般情况下,如果自定义的类会产生很多对象,比如人,学生,书,通常都需要覆盖equals,hashCode方法。 建立对象判断是否相同的依据。 import java.util.HashSet; import java.util.Iterator; import java.util....