繁体   English   中英

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

[英]Java constructor is not so intuitive. Or perhaps it's not Java, it's C# that is not intuitive

给定此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); }
}

使用这个相同的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); }
}

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

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

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

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

Java中发生了什么:

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

C#发生了什么:

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

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

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

Java中的初始化顺序:

1.将实例的存储擦除为零,自动将对象中的所有基元设置为其默认值(数字为零,布尔值和字符等效)和对null的引用。

2.调用基class A构造函数。 它将调用class Bprint方法,因为它是一个重写方法。 i现在才0。

3.执行B类的成员初始化。 所以i现在才4岁。

为了不产生这种意外,不要在构造函数中调用任何非静态或非私有方法,因为它们可能在派生类中被重写。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM