请忽略我的傲慢......这几天学习java,我遇到了一个完全相同的问题:Why can't I instantiate and create Object without main method? (Stack Overflow Error)
也期待可能的downvote ...但请一次回答我的问题!!!!
我正在尝试的代码:
public class Arrayprg{
Arrayprg ag = new Arrayprg(); //ignore this for a while and go thru code please
public static void main(String []args){
System.out.println("Hello Array");
new Arrayprg().declarearray();
}
public void declarearray()
{
int[] arr;
arr = new int[11];
new Arrayprg().assignarr(arr);
}
public void assignarr(int arr[])
{
int i;
for(i = 0; i < 11; i++)
{
arr[i] = i;
}
new Arrayprg().printarr(arr);
}
public void printarr(int arr[])
{
int i;
for(i = 0; i < 11; i++)
{
System.out.println(arr[i]);
}
}
}
从逻辑上思考,通过代码你会看到很多new arrayprg()
....我想到的是instantiate outside of methods
并在之后通过它调用所有方法,但我猜它是在java中不允许。
导致我的问题的原因
通过引用问题解决方案,因为它解释了下面的事情发生了:
Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
该问题中给出的 解释
.....只要实例化类的实例,它就会被初始化。这将永远不会终止,直到你的内存不足并导致堆栈溢出。使用调试器运行它以获得更清晰的视图。
我的问题
所以我的程序中有Arrayprg ag = new Arrayprg();
,每次创建一个实例时都会创建一个循环,但是当我通过new Arrayprg().
调用函数时,为什么会调用它?
我的意思是,当我在方法中通过new Arrayprg()
调用函数时,为什么调用Arrayprg ag = new Arrayprg();
并为Stackoverflow创建错误循环?????
答案 0 :(得分:5)
此将导致StackOverflowError。
有趣的是,你告诉我们忽略的那条线是罪魁祸首。当您实例化一个新的Arrayprg
时,会调用任何对象初始值设定项,包括 new Arrayprg()
,然后递归尝试继续调用构造函数而不是结束。删除该行,或将其放在静态初始化程序中。更好的是,只是不要在main方法之外创建Arrayprg
,因为你的Arrayprg不需要Arrayprg本身的实例,
我会更清楚,但我不知道你想要达到的目标。
答案 1 :(得分:1)
每次创建Arrayprg
的实例时,都会调用此行:Arrayprg = new Arrayprg();
,这意味着每次创建一行时,它都会创建另一个,另一个和另一个等。您可以在那里实例化对象,但实例化另一个相同类型的对象会导致无限循环。
此外,在您的方法(declareArr,assignArr等)中,您可以删除'new Arrayprg()。并只调用现有对象上的函数。
答案 2 :(得分:1)
解决方案:
更改此行:
Arrayprg = new Arrayprg(); //ignore this for a while and go thru code please
为:
static Arrayprg a = new Arrayprg();
并且您将不再获得无限递归问题,因为它现在只会创建一个在所有实例之间共享的实例 - 而不是每个实例立即创建一个新实例。
解释
作为在Java中构造Object的一部分,所有成员变量初始化器,初始化器代码块等都被调用,以及构造函数本身。
因此,为了创建一个新的Arrayprg,它所做的一件事就是寻找需要初始化和初始化它们的成员变量。
在这种情况下,它会找到Arrayprg a = new Arrayprg();
,因此为了初始化字段a
,它会尝试创建新的Arrayprg()
。
但是新的Arrayprg()
会再次完成相同的过程,并且会再次,等等。
有很多方法可以解决此问题 - 包括:
为什么在方法调用中不会发生这种情况:
导致递归的重要因素是调用在创建新对象期间发生。如果尝试创建一个新对象涉及创建同一对象的另一个副本,那么最终将导致无限递归,从而导致失败。
所以你可以随心所欲地创建一个新对象 - 只要它不在自己的创建中。
class A {
A a = new A(); // Recursion
}
class A {
A() {
A a = new A(); // Recursion
}
}
class A {
A getNewA() {
return new A();
// This is fine as it doesn't happen during creation of an A
}
}
class A {
A() {
getNewA();
// Recursion as calling getNewA creates a new A, which calls getNewA, which....
}
A getNewA() {
return new A();
// This is fine on its own but is broken if called from the constructor
}
}
class B {
A a = new A();
// This is fine as B is not A, so you can create a new A within B.
}
答案 3 :(得分:1)
让我们直观地介绍一下。
Arrayprg = new Arrayprg();
那么你需要创建一个Arrayprg
类型的对象?那么你需要创建它的字段。
Arrayprg = new Arrayprg();
再一次,你告诉JVM给你另一个Arrayprg
对象。根据定义,这意味着制作另一个Arrayprg
对象。
这会给你一个StackOverflowException
。
解决方案?
你不应该真的像这样嵌套类型。这是毫无意义。你已经在里面这个类,所以使用它的方法。
public void declarearray()
{
int[] arr;
arr = new int[11];
assignarr(arr);
}
遵循此模式,您将无需使用Arrayprg
字段。
答案 4 :(得分:0)
在类中,您可以在任何方法之外创建对象,对象不能属于同一个类。
没有意义。以此为依据。