`
bantouyan
  • 浏览: 146284 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java集合类hashCode错误之StackOverflowError

    博客分类:
  • Java
阅读更多

      前段时间写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集合设计的一个失误。既然应用中有可能出现集合间的循环引用,就应该避免这种错误出现。

 

2
6
分享到:
评论
3 楼 bantouyan 2011-03-28  
裴小星 写道
guibin 写道
第二行代码,为什么要新建一个list,然后自己把自己加进去?这样做有什么特殊的用途吗?

为了测试循环引用吧,自己引用自己。我觉得一般也不会这么做。


你说的对,只是一个测试而已,现实中谁也不会这么做,但有可能出现间接引用。
2 楼 裴小星 2011-03-20  
guibin 写道
第二行代码,为什么要新建一个list,然后自己把自己加进去?这样做有什么特殊的用途吗?

为了测试循环引用吧,自己引用自己。我觉得一般也不会这么做。
1 楼 guibin 2011-03-20  
第二行代码,为什么要新建一个list,然后自己把自己加进去?这样做有什么特殊的用途吗?

相关推荐

Global site tag (gtag.js) - Google Analytics