public class TestClass(){
public static void main(String []args) {
TestClass t1 = new TestClass();
t1.anything();
}
}
在同一个类的定义中创建一个对象并不奇怪吗?因为然后作为响应 - 这个对象创建一个新对象,然后这个新对象创建另一个,并且无限循环开始永远不会结束,直到内存已满。
答案 0 :(得分:21)
在同一个类的定义中创建一个对象并不奇怪 比响应对象创建一个新对象然后这个新对象 创建另一个并开始无限循环
不,主程序只在您运行程序时运行一次。它不会再被执行。因此,该对象只会被创建一次。
想想你的主要方法是在课外。这将创建您的类的实例,并使用创建的实例。因此,当您从main
方法创建实例时,将调用构造函数来初始化实例的状态,然后在构造函数返回时,执行main方法的下一个语句。
实际上,您可以认为main
方法不属于您班级实例的状态。
但是,如果你在构造函数中创建了类的实例(比如0-arg),并且引用作为实例引用变量,那么它将变成无限递归。
public class A {
private A obj;
public A() {
obj = new A(); // This will become recursive creation of object.
// Thus resulting in StackOverflow
}
}
答案 1 :(得分:5)
如果您尝试执行以下操作,则只会出现无限循环(堆栈溢出错误):
public class TestClass {
public TestClass() {
TestClass t = new TestClass();
}
}
在其他地方,您尝试创建类TestClass
的对象。
答案 2 :(得分:2)
这并不奇怪。我所知道的所有面向对象语言都允许这样做。代码在语义上是对象定义的一部分,但在实践中,它可以被认为与任何给定对象的实际状态分开。因此没有循环,因为对象构造不会调用您的方法(当然,除非它确实 - 然后您有问题)。
答案 3 :(得分:1)
当你使用new来创建对象时,会调用构造函数来初始化实例变量,直到你的超类的所有构造函数都被调用为止。 如果你把一些代码放在构造函数中,每次你创建一个对象时都会运行它
答案 4 :(得分:1)
当程序启动时,它执行main方法。在java中,您无法在类之外创建方法。所有方法都必须封装在一个类中。因此,作为程序入口点的主要方法必须在一个类中。当您运行此程序时,main方法将运行一次并将执行其中的代码。在您的情况下,它创建一个封闭类TestClass
的对象。这不一定会发生。它也可以在这个类之外创建对象。你只会得到@adarshr的答案中解释的无限循环。
答案 5 :(得分:1)
public class TestClass{
public static void main(String []args) {
TestClass t1 = new TestClass();
t1.anything();
}
}
这是一个非常有效的代码。调用main
方法时,不存在TestClass
的先前实例(不需要,因为main
方法为static
)。
public class Test2{
public Test2 clone(){
return new Test2();
}
}
这也完全有效。当您创建Test2的新实例时,它包含clone
方法,但该方法不会自动执行。只有在调用clone
方法时,才会创建另外一个Test2实例。
public class MyLinkedList{
MyLinkedList next;
MyLinkedList(int elems){
if(elems>0){
next = new MyLinkedList(elems-1);
}else{
next = null;
}
}
}
也完全有效,即使构造函数使用相同的构造函数创建新实例,因为创建由条件保护,因此创建实例有时会触发新创建。
public class Fail{
public Fail(){
new Fail();
}
}
这是唯一有问题的例子。编译器没有抱怨。 可以转换为字节代码,可以执行。但是,在运行时,会导致堆栈溢出:
编译器允许这样做,因为通常编译器不能阻止所有无限递归。编译器允许任何可以转换为字节码的内容。
但是,如果编译器检测到方法或方法链无条件地调用,则可能发出警告。
答案 6 :(得分:1)
一点都不奇怪。你看,main()
方法是执行的起点。因此,形象地说,java 是“盲目的”(看不到您告诉它执行/运行的内容),除非它“看到”了 main()
方法。在“看到” main()
方法之后,它现在有能力执行后面的其他指令,所以作为外卖,main()
方法字面上不属于它自己的类中的对象第一名。
对于递归,它只会在您执行类似@Rohit Jain 所说的操作时发生。或者根据您的代码,您不调用 anything
,而是调用 main()
本身。
public static void main(String []args) {
TestClass t1 = new TestClass();
main(String[] args);
}
}
引用变量 t1
实际上没有调用 main
,因为它是静态的。好消息是,main
不是由您的代码调用,而是由“jvm”调用,因此严格来说,您无法从那里删除静态。它会导致一些好的错误消息明确告诉您静态应该在那里。这就是为什么您会看到 main()
未被上述代码段中的对象调用。
如果你做了这些,那么除此之外还会发生递归,你可以安全地在它自己的类中创建一个对象。尽管如此,我不建议这样做。让一个类具有 main()
方法并在该 Main 类(包含 main 方法的类)中实例化(创建对象)其他类。这样你就可以运行一次代码。