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

标签 java c# constructor

给定这段 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

using System;

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 中发生了什么:

  • (empty, implicit) B 的构造函数被调用
  • 调用 A 的父类(super class)构造函数(打印 0 因为 i 未初始化)
  • i 在父类(super class)构造函数之后初始化
  • print() 被调用(打印 4)

C# 中发生了什么:

  • (empty, implicit) B 的构造函数被调用
  • 调用父类(super class)构造函数之前被初始化
  • 调用 A 的父类(super class)构造函数(打印 4 因为 i 已经初始化)
  • print() 被调用(打印 4)

既不是对也不是错——这只是编译器对构造操作排序的方式不同而已。我个人认为 Java 排序稍微更合乎逻辑,因为对我来说,在子类初始化发生之前完全构建父类(super class)是有意义的。

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

关于java - 为什么 C# 构造函数行为与 Java 不同,反之亦然?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10611726/

相关文章:

java - 如何以简洁的方式调用 super 构造函数

java - 使用 EclipseLink 在 Oracle 上执行查询时出现奇怪的行为

java - 创建超过 30gb 的 EC2 实例 - 在 Java 中

没有命名空间的 C# XElement

c# - 在什么时候我需要处理我的自定义 WPF 用户控件?

c++ - 覆盖基类调用的函数?

java - 上传 MySQL 数据库并从远程系统访问 Java 应用程序

java - 为什么当你从第二个继承中调用父方法时是从第一个继承中调用?

c# - 锁定列表会产生死锁

C++ 错误 : "expected constructor, destructor, or type conversion before ' <' token