给定这个 Java 代码,输出0 and 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 and 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 中发生了什么:
- (空,隐式)调用 B 的构造函数
- A 的超类构造函数被调用(打印 0,因为 i 未初始化)
- 我已初始化after超类构造函数
- print() 被调用(打印 4)
C# 中发生了什么:
- (空,隐式)调用 B 的构造函数
- 我已初始化before调用超类构造函数
- A 的超类构造函数被调用(打印 4,因为 i 已经初始化)
- print() 被调用(打印 4)
两者都没有对错之分——只是编译器如何排序构造操作的不同。就我个人而言,我认为 Java 顺序稍微更符合逻辑,因为对我来说,在子类初始化发生之前完全构造超类是有意义的。
无论哪种方式,因为逻辑可能变得非常复杂,所以我建议您通常避免在对象构造期间调用虚拟方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)