Java构造函数不是那么直观.或许它不是Java,它的C#不直观

Hao*_*Hao 6 c# java rationale

给定此Java代码,此输出0和4:

class A{
   A() {  print();   }
   void print() { System.out.println("A"); }
}

class B extends A{
   int i =   Math.round(3.5f); 

   public static void main(String[] args){
      A a = new B();
      a.print();
   }
   void print() { System.out.println(i); }
}
Run Code Online (Sandbox Code Playgroud)

使用这个相同的C#代码,输出4和4

使用系统;

class A{
   internal A() {  print();   }
   virtual internal void print() { Console.WriteLine("A"); }
}

class B : A{
   int i =  (int) Math.Round(3.5f); 

   public static void Main(string[] args){
      A a = new B();
      a.print();
   }
   override internal void print() { Console.WriteLine(i); }
}
Run Code Online (Sandbox Code Playgroud)

虽然我发现Java上的输出应该是4和4,但答案实际上是Java上的0和4.然后我在C#中尝试了它,答案是4和4

是什么赋予了?Java的基本原理是,在构造B时,A仍在初始化(因此,如果Java表示A仍在初始化,我假设B仍在初始化),因此默认值应为0.因此Java中的输出为0和4.

为什么C#构造函数行为与Java不同,反之亦然?

mik*_*era 8

它正在发生,因为构造函数中对象初始化的顺序不同.

Java中发生了什么:

  • (空,隐式)调用B的构造函数
  • 调用A的超类构造函数(因为我未初始化而打印0)
  • 我是超类构造函数之后初始化的
  • 调用print()(打印4)

C#发生了什么:

  • (空,隐式)调用B的构造函数
  • 调用超类构造函数之前初始化
  • A的超类Construtor被调用(打印4,因为我已经初始化)
  • 调用print()(打印4)

无论是对还是错 - 这只是编译器命令构造操作的一个区别.我个人认为Java排序略显合乎逻辑,因为我认为超类是在子类初始化之前完全构造的.

无论哪种方式,因为逻辑可能会变得非常复杂,我建议您在对象构造期间避免调用虚方法.