一道程序初始化顺序题目引起的讨论

来源:互联网 发布:linux route指令 编辑:程序博客网 时间:2024/05/20 09:46
遇到了一个题目,题目就相当于下面的代码。本人那个时候答对了,也就没有细细品味。

今天朋友正好也遇到了,他用Java写的时候代码如下:

package com.nowcoder;/* * @decription: */public class ClassInit {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubC c = new C();}static public class A{B b = new B();public A() {System.out.println("A");}}static public class C extends A{B b = new B();public C() {System.out.println("C");}}static public class B{public B() {System.out.println("B");}}}
java他用的内部类,因为是静态的main函数,他声明的内部类都是static类型。本人的理解,static类应该只会初始化话一次,但实际上
C c = new C();
写两次,就会调用两次。可能这就是内部类不同的地方。

我本人熟悉C#和C++,所以也写了一份:

C++版本

#include "stdafx.h"#include <iostream>using namespace std;  class B{ public: B() {cout<<"B"<<endl;}}; class A{public:B b;A() {cout<<"A"<<endl;}};  class C :public A{public: B b;C() {cout<<"C"<<endl;}};int _tmain(int argc, _TCHAR* argv[]){C c;return 0;}

C#版本

  class Program    {        static void Main(string[] args)        {            C c = new C();            Console.ReadKey();        }    }     public class A{ B b = new B();public A() {            Console.WriteLine("A");}} public class C : A{B b = new B();public C() {//System.out.println("C");            Console.WriteLine("C");}} public class B{public B() {            Console.WriteLine("B");}}

然后C#的答案和C++,Java不同,因此引出了如下讨论:


java与C#初始化顺序区别,及其原因初探

java与C#的初始化顺序有一点点区别,在网上找到了一个顺序及示例如下:

http://blog.sina.com.cn/s/blog_a072b6c401012nzp.html

在JAVA的初始化子类的执行顺序是:
1.先初始化父类的成员变量
2.再调用父类的构造方法
3.再初始化子类自己的的成员变量
4.再调用子类自己的构造方法

在C#中则是这样:
1.先子类字段初始化 
2.然后父类字段初始化 
3.再执行父类构造函数 
4.最后执行子类构造函数

以下附上代码及执行结果:
Java:
class X {
Y b = new Y();

X() {
System.out.print("X");
}
}

class Y {
Y() {
System.out.print("Y");
}
}

public class Z extends X {
Y y = new Y();

Z() {
System.out.print("Z");
}

public static void main(String[] args) {
new Z();
}
}

执行结果:
YXYZ

C#:
namespace ConsoleApplication1
{
    class X
    {
        Y y = new Y();
        public X()
        {
            Console.Write("X");
        }
    }
}
namespace ConsoleApplication1
{
    class Y
    {
        public Y()
        {
            Console.Write("Y");
        }
    }
}
namespace ConsoleApplication1
{
    class Z : X
    {
        Y y = new Y();
        public Z()
        {
            Console.Write("Z");
        }
        static void Main(string[] args)
        {
            new Z();
            Console.ReadLine();
        }
    }
}

执行结果:
YYXZ
java的构造函数中的多态方法会有问题,C#中就不会有问题了。

但是java中子类的成员变量可以用父类的成员变量初始化,C#的字段就不行了。


java完整初始化顺序:

C#完整初始化顺序:

1: 子类静态变量

2: 子类静态构造函数

3: 子类非静态变量

4: 父类静态变量

5: 父类静态构造函数

6: 父类非静态变量

7: 父类构造函数

8: 子类构造函数



java初始化的详细解释:

http://blog.csdn.net/yangyan19870319/article/details/6202403

final 成员变量的初始化:

http://blog.csdn.net/jiafu1115/article/details/6734639


C#的初始化由于未没有代码段变得明了不少,类的成员与java过程类似,静态常量必须赋值,自动变量必须赋值。

0 0
原创粉丝点击