繁体   English   中英

Java中的递归泛型定义和Stackoverflow

[英]Recursive generic definitions and Stackoverflow in Java

我正在为一些研究项目编写确定性有限自动机的实现,并且有一些弧导致相同的状态。 我为State编写了这个类,但我想知道为什么代码会产生Stackoverflow:

 public class State extends HashMap<Character, HashSet<State>>
 {
    public static void main(String[]args)
    {
       State t=new State();
       t.addTransition('a',t);
       t.addTransition('b',t);
    }
    public void addTransition(Character symbol, State t )
    {
        if(!this.containsKey(symbol))
        {
            this.put(symbol, new HashSet<State>());
        }
        this.get(symbol).add(t);
    }
}

令人惊讶的是,如果我删除其中一个“addTransition”调用,则没有错误。

我的Java版本是JDK 1.6.37,操作系统是Ubuntu Linux 12.04。

* UPD: *堆栈跟踪是:

Exception in thread "main" java.lang.StackOverflowError
at java.util.HashMap$KeyIterator.<init>(HashMap.java:843)
at java.util.HashMap$KeyIterator.<init>(HashMap.java:843)
at java.util.HashMap.newKeyIterator(HashMap.java:857)
at java.util.HashMap$KeySet.iterator(HashMap.java:891)
at java.util.HashSet.iterator(HashSet.java:170)
at java.util.AbstractSet.hashCode(AbstractSet.java:122)
at java.util.HashMap$Entry.hashCode(HashMap.java:737)
at java.util.AbstractMap.hashCode(AbstractMap.java:494)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
at java.util.HashMap$Entry.hashCode(HashMap.java:737)
at java.util.AbstractMap.hashCode(AbstractMap.java:494)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
at java.util.HashMap$Entry.hashCode(HashMap.java:737)
...
at java.util.AbstractMap.hashCode(AbstractMap.java:494)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
at java.util.HashMap$Entry.hashCode(HashMap.java:737)
at java.util.AbstractMap.hashCode(AbstractMap.java:494)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
at java.util.HashMap$Entry.hashCode(HashMap.java:737)

任何意见?

运行此程序后,我认为问题如下:由于您要添加从节点到自身的转换,因此您最终会得到一个将字符映射到自身的HashMap 当您尝试添加第二个转换时,它需要将对象添加到HashSet 问题是,为了做到这一点,它需要为您的对象计算哈希码。 由于您的对象扩展了HashMap ,它使用HashMap代码来计算对象的哈希代码。 为此,它尝试递归地构造HashMap中包含自身的所有对象的哈希代码。 因此,它递归地尝试计算自己的哈希码,这需要它计算自己的哈希码,这需要它计算自己的哈希码等。

我不确定这是什么最好的解决方案,但我会从没有这个对象扩展HashMap 当你意味着使用组合时,通常认为使用继承是一个坏主意 使HashMap成为对象的直接字段意味着您将打破此循环,因为Java将使用hashCode的默认实现,而hashCode不会尝试为对象计算深度哈希代码。

希望这可以帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM