Java的构造不那么直观。 也许它不是Java的,这是C#是不直观(Java construct

2019-09-17 06:26发布

鉴于这种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,但得到的答复居然是0和4上的Java。 然后我试图在C#中,答案是4和4

是什么赋予了? 爪哇理由是,建筑B的过程中,A仍在初始化(因此我断定如果爪哇所述A仍在初始化乙仍在初始化),所以默认值应该是0。因此输出为0,并在Java中4。

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

Answer 1:

它的发生是因为在对象初始化的构造函数的顺序上的差别。

什么是发生在Java中:

  • B的(空的,隐式的)构造被称为
  • A的超类Construtor被称为(打印0,因为i被未初始化)
  • 我是父类的构造初始化
  • 打印()被调用(打印纸4)

什么是发生在C#:

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

无论是对还是错 - 它只是在编译器如何定购施工作业的差异。 我个人认为,Java的排序是一个稍微更合乎逻辑的,因为这对我来说很有意义的子类初始化发生之前超类完全构造。

无论哪种方式,因为逻辑可以得到相当复杂,我建议你避免调用,一般对象施工过程中的虚方法。



Answer 2:

在Java中初始化的顺序:

实例的存储1.擦拭为零,在对象中的所有原语自动设置为默认值(零号,等效于布尔和焦炭),并引用为null。

碱的2.构造class A被调用。 它将调用print在方法class B ,因为它是一个重写的方法。 i是0,在这一刻。

执行B类3,成员初始化。 所以, i是4了。

为了不产生这样的惊喜,不调用构造函数的任何非静态或非私有方法,因为它们可以在派生类中重写。



文章来源: Java constructor is not so intuitive. Or perhaps it's not Java, it's C# that is not intuitive