[英]Java compilation confusion: why does this code compile?
我不确定为什么此代码(在运行时提供stackoverflow)会编译:
import java.io.*;
import java.util.*;
public class StackOverflow {
StackOverflow overflow = new StackOverflow();
public void myCall() {
overflow.myPrint();
}
public static void main(String[] args) {
StackOverflow newStackOverflow = new StackOverflow();
newStackOverflow.myCall();
}
public void myPrint() {
System.out.println("I am confused!");
}
}
我感到困惑的原因是,在类定义中,我试图创建要定义的类的对象。 这不是编译时错误吗?
这不是编译时错误,因为编译器无法确定它是否将在编译时无限生成。
您和我可以查看并确定看到它,但是编译器只关心声明是正确的。 该声明在语法上没有任何非法之处,这就是为什么编译器将其放任不管。
它与停止问题有关 ,因为程序无法报告是否成功停止。
我想可以认为,编译器应捕获此无限循环的递归版本,但是语言定义中没有任何内容使对象在实例化时构造其自身的另一个实例是非法的。
我当然希望像FindBugs这样的代码分析工具会抱怨。
不,这不是Java的问题。 动态声明非常快速和宽松,不需要在使用之前声明它们。 稍后再进行说明,并使该语言更易于使用。
它为您提供了堆栈溢出异常,因为每次创建StackOverflow时,该行
StackOverflow overflow = new StackOverflow();
创建另一个StackOverflow,再创建另一个StackOverflow,依此类推,直到堆栈最大化并引发异常。
不会。Java不会在编译时检测无限循环或无限递归。 您可以像下面这样编译您的代码或下面的方法,它将在运行时崩溃。
private int recurseForever(){
return recurseForever();
}
在您的情况下,构造函数将创建该类的新实例,从而调用另一个构造函数,依此类推。
至于为什么它不这样做:因为不可能在所有情况下都这样做(停止问题),并且无法将资源投入到部分解决方案中(这仅在某些时候起作用,但总是对每个人都降低了编译速度,可能还引入了错误)因为现在编译器更加复杂),显然不是一个好主意。
由于编译器实际上不可能捕获您可以做到的所有可能方式,因此不需要编译器捕获它。 通常,无限递归只能在运行时检测到。 (即使那样,您仍然可以检测到它超出了允许的限制。)
我感到困惑的原因是,在类定义中,我试图创建要定义的类的对象。 这不是编译时错误吗?
当编译器看到这段代码时,您已经完全定义了您的类,并且编译器可以毫不含糊地创建此类的对象。 因此,这表明没有编译时错误。
不,它不应该通过编写以下代码行来产生错误: StackOverflow overflow = new StackOverflow();
您实际上是在类中创建实例变量。 这行StackOverflow newStackOverflow = new StackOverflow();
将创建您的局部变量。
如果您按照以下方式更新代码,那么它也将起作用。
import java.io.*;
import java.util.*;
public class StackOverflow {
private static StackOverflow overflow = new StackOverflow();
public void myCall() {
overflow.myPrint();
}
public static void main(String[] args) {
overflow.myCall();
}
public void myPrint() {
System.out.println("I am confused!");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.