我一直在使用Java中的递归构造函数。编译器接受以下类,Java中的两个递归构造函数示例。它在运行时使用java 1.7.0_25和Eclipse Juno(版本:Juno Service Release 2 Build id:20130225-0426)与StackOverflowError崩溃。
class MyList<X> {
public X hd;
public MyList<X> tl;
public MyList(){
this.hd = null;
this.tl = new MyList<X>();
}
}
错误消息是有道理的,但我想知道编译器是否应该捕获它。反例可以是带有构造函数的整数列表,该构造函数将int作为参数,如果参数小于零,则将this.tl
设置为null。这似乎是合理的,允许以允许递归方法的方式,但另一方面,我认为构造函数应该终止。是否应该允许构造函数调用自己?
所以我在提交Java错误报告之前要求更高级的权限。
编辑:我主张进行简单的检查,例如禁止构造函数调用自身或Java开发人员为解决https://bugs.openjdk.java.net/browse/JDK-1229458所做的任何事情。一个更荒谬的解决方案是检查递归构造函数调用的参数是否在某些有根据的关系中正在减少,但问题的关键不在于“Java应该确定所有构造函数是否终止?”而是“在编译构造函数时Java应该使用更强的启发式算法吗?”。答案 0 :(得分:3)
我没有看到任何理由为什么构造函数应该比任何其他类型的函数更需要终止。但是,与任何其他类型的函数一样,编译器cannot infer在一般情况下是否会终止此函数(停止问题)。
现在是否通常需要一个递归构造函数是值得商榷的,但它肯定不是一个bug,除非Java规范明确声明递归构造函数调用必然会导致错误。
最后,区分递归调用相同对象的构造函数是很重要的,这是一个常见的模式,例如克服缺少默认参数,并调用构造函数创建另一个对象的同一个类,如您的示例所示。
答案 1 :(得分:3)
你甚至可以拥有几个具有不同参数的构造函数,并使用this(...)
相互调用。通常,通过计算机科学,不能始终保证代码的终止。在这个简单的情况下,一些智能会很好,但是可能不需要编译器错误。 有点像无法访问的代码。然而,我眼中的构造函数或普通方法没有区别。
答案 2 :(得分:1)
虽然这种特殊情况似乎很明显,但确定代码是否终止是一个不可能回答的问题。
如果您尝试为无限递归配置编译器警告,则会遇到the Halting Problem:
“鉴于任意计算机程序的描述,决定是否 程序完成运行或继续运行。“
阿兰图灵在1936年证明了一种通用的算法来解决问题 所有可能的程序输入对的暂停问题都不存在。