`

面试题--类成员变量的初始化时间

 
阅读更多
class B {
	B() {
		System.out.println("B");
		go();
	}
	private int a=1;
	public void go(){
		System.out.println("a="+a);
	}
}

public class A1 extends B {
	A1() {
		System.out.println("A1");
	}
	private int a=11;
	public void go(){
		System.out.println("a="+a);
	}
	public static void main(String[] args) {
		new A1();
	}
}

以上代码输出结果为: 
B
a=0
A1

 

我当时以为是输出a=11,结果回来跑了一把代码后,发现为0,即:先执行A1这时只是申明变量,并没赋值,然后执行B(),这时获取到a是A1里的,但还是初始值0呢,所以输出0.

后来经资料官方的解释为:对类变量的初始化是在执行完其构造方法的第一行代码(即this或super)后才开始的。

 

以下代码可以证实:

class B {
	B() {
		final B b=this;
		go();
		new Thread() {
			public void run() {
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				b.go();
			}
		}.start();
	}
	public void go(){
	}
}

public class A1 extends B {
	A1() {
		System.out.println("aa");
		go();
	}
	private int a=11;
	public void go(){
		System.out.println("a="+a);
	}
	public static void main(String[] args) {
		new A1();
	}
}

输出结果为:

a=0
aa
a=11//这个是23行输出的
a=11//这个是12行输出的,由于另起了线程,所以在输出的时候已经执行完了构造方法

1
5
分享到:
评论
4 楼 cwj158 2011-09-13  
super
Rainbow702 写道
引用
后来经资料官方的解释为:对类变量的初始化是在执行完其构造方法的第一行代码(即this或super)后才开始的。

这句话是OK的,你可以在 B 类的构造函数中的第一行加个
super();

然后 DEBUG 一下就知道了。
其他的你应该这么理解:
在新建一个A1实例时,B类的构造函数要先被调用,在B类的构造函数中有一句是调用了  go()  方法的,由于 A1 类中重写了这个方法,所以会来调用 A1 中的这个方法,但此时,A1 中的 a 变量还没有被初始化,所以打印出来的是 0.

嗯,好办法哈。
3 楼 Rainbow702 2011-09-11  
引用
后来经资料官方的解释为:对类变量的初始化是在执行完其构造方法的第一行代码(即this或super)后才开始的。

这句话是OK的,你可以在 B 类的构造函数中的第一行加个
super();

然后 DEBUG 一下就知道了。
其他的你应该这么理解:
在新建一个A1实例时,B类的构造函数要先被调用,在B类的构造函数中有一句是调用了  go()  方法的,由于 A1 类中重写了这个方法,所以会来调用 A1 中的这个方法,但此时,A1 中的 a 变量还没有被初始化,所以打印出来的是 0.
2 楼 cwj158 2011-09-11  
瘋叻ハ.兩 写道
第二个程序中final B b = this; 你想表达什么吗?

首先谢谢你关注我的代码哈,
主要是我想在第12行调用b.go(); 但由于内部类不能访问外部类方法中的局部变量,除非变量是final的(一般发生在方法中定义的内部类)。所以只能加个FINAL。
1 楼 瘋叻ハ.兩 2011-09-11  
第二个程序中final B b = this; 你想表达什么吗?

相关推荐

Global site tag (gtag.js) - Google Analytics