有人可以详细说明一下下面的场景吗,如果解释包括三种情况的内存分配和引用会更方便:
- 三种情况下的流程是如何执行的?
- 为什么三种情况下的流程不同?
- 虽然这两个类之间存在循环依赖,但为什么在其余情况失败的情况下单独执行情况 1?
案例一
namespace CircularDependency_1
{
class Program
{
static void Main(string[] args)
{
A a = new A();
Console.WriteLine("executed");
Console.ReadLine();
}
}
public class B
{
public static A a = new A();
public B()
{
Console.WriteLine("Creating B");
}
}
public class A
{
public static B b = new B();
public A()
{
Console.WriteLine("Creating A");
}
}
}
输出
Creating A
Creating B
Creating A
executed
案例二
namespace CircularDependency_1
{
class Program
{
static void Main(string[] args)
{
A a = new A();
Console.WriteLine("executed");
Console.ReadLine();
}
}
public class B
{
public static A a;
public B()
{
a = new A();
Console.WriteLine("Creating B");
}
}
public class A
{
public static B b;
public A()
{
b = new B();
Console.WriteLine("Creating A");
}
}
}
输出 进程因 StackOverflowException 而终止。
案例三
namespace CircularDependency_1
{
class Program
{
static void Main(string[] args)
{
A a = new A();
Console.WriteLine("executed");
Console.ReadLine();
}
}
public class B
{
public A a;
public B()
{
a = new A();
Console.WriteLine("Creating B");
}
}
public class A
{
public B b;
public A()
{
b = new B();
Console.WriteLine("Creating A");
}
}
}
输出 进程因 StackOverflowException 而终止。
最佳答案
@Versatile,你很接近,但不对。第一种情况执行而其他两种情况失败的原因不仅仅是因为对象是在构造函数内部或类内部(构造函数外部)创建的。为了证明这一点,请尝试使 B
和 A
类中的 a
和 b
字段不是静态的(案例一), 分别;你会看到它会失败,即使对象是在构造函数之外创建的。
由于@Versatile 解释的原因,案例 2 和案例 3 失败了。
案例 1 的执行是因为 static
成员。
让我们检查流程:
在 Main
方法中,A a = new A()
行开始创建 a
对象。在此过程中,将创建 B
类的对象,因为 public static B b = new B()
行 - 正是这一行将开始创建类的另一个对象类 A
因为类 B
主体中的行 public static A a = new A()
。现在,魔法来了(不会引发循环依赖)。这行 public static A a = new A()
将开始创建类 A
的另一个对象,在创建此对象时它不会创建类 的另一个对象>B
因为它是 A
的静态成员,而且它已经被创建了。众所周知,类的静态成员在该类的所有实例之间共享。因此,它不会触发类 B
的另一个对象的创建。总的来说,我们最终得到了类的三个实例,顺序为:A
、B
、A
。
更新
有趣的是,在第一种情况下,如果我们在构造函数中初始化静态成员会发生什么。即使 A
和 B
类声明了静态成员,执行也会因循环依赖而失败。这是因为在执行构造函数之前,静态成员没有被初始化。
关于java - 为什么以下案件的执行流程不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42255539/