Java大神、小妖,面试题来了

专业打酱油 发布于 2013/07/25 10:16
阅读 766
收藏 2
public class A {


 static class R{
 
 void t(){
 System.out.println("R.t");
 }
 
 public R() {
 System.out.println("R before");
 t();
 System.out.println("R after");
 }
 }
 
 static class Rr extends R{


 private int n = 1;
 void t(){
 System.out.println("Rr.t");
 System.out.println("Rr.n : " + this.n);
 }
 
 public Rr(int n) {
 System.out.println("Rr before");
 this.n = n;
 System.out.println("Rr.n : " + this.n);
 System.out.println("Rr after");
 }
 }
 
 public static void main(String[] args) {
 
 new Rr(3);
 }
}
R before
Rr.t
Rr.n : 0
R after
Rr before
Rr.n : 3
Rr after

1、解释一下输出过程?

2、为什么黑色粗体能执行n的值是0?Rr的t为什么可以在Rr的初始化方法前执行?

加载中
0
looqy
looqy
子类初始化的时候首先会去执行父类的构造方法,输出R.before,但是执行到t方法的时候执行的是子类的t方法,此时子类中的n并未赋值,只能打印出来系统缺省值0,然后输出after,输出3,具体为啥会执行子类的t方法而不是父类的t方法你可以参考下java编程思想中关于子类、父类以及静态内部类的原理解释,反正我看这一段的时候挺晕乎的。。。。一点拙见,求大神指正
0
winnie_tour
winnie_tour
补充楼上的,实际上执行new Rr(3),时候会走到Rr的构造方法里,因为Rr继承R,java中如果父类存在默认的构造方法,会先执行,所以在执行Rr构造方法中的代码前会先执行R构造方法中的代码,当走到R的t()时候,发现Rr重写了这个方法所以就会执行Rr的t(),然后继续走完R的构造方法,在继续执行Rr的构造方法
0
daxiaoming
daxiaoming

引用来自“looqy”的答案

子类初始化的时候首先会去执行父类的构造方法,输出R.before,但是执行到t方法的时候执行的是子类的t方法,此时子类中的n并未赋值,只能打印出来系统缺省值0,然后输出after,输出3,具体为啥会执行子类的t方法而不是父类的t方法你可以参考下java编程思想中关于子类、父类以及静态内部类的原理解释,反正我看这一段的时候挺晕乎的。。。。一点拙见,求大神指正
这位仁兄回答很标准。关于为啥会执行子类的 t 方法?因为 Java 对类的方法绑定是运行期绑定(late binding),而不是编译期绑定(early binding)。所以在一个 Rr 对象上调用 t(),肯定是调用了它自己的 t() 方法。你也可以想,如果不是这样,那么 @override 就没有必要存在了。
0
白黑白
白黑白
补充一点:你再t();前打印这个System.out.println(this.getClass());会发现打印出来的是Rr,而不是R
专业打酱油
专业打酱油
回复 @白黑白 : 问题是这样的 1子类初始化 2发现有父类存在 3执行父类的构造方法 4父类构造方法中调用了一个方法! 5子类发现重写了父类的这个方法! 6调用了子类的方法 换个角度:如果直接在子类的构造方法中调用子类其他的方法,我们都觉得毫无问题。 但是4,5,6步骤时候让人迷惑!why?
专业打酱油
专业打酱油
回复 @白黑白 : 你的意思是说还没有执行完成Rr的构造方法就已经new出来Rr对象吗?
白黑白
白黑白
回复 @专业打酱油 : new Rr(3)调用的就是public Rr(int n);在这一步已经new 出Rr对象了,所以你在t();前打印this.getClass()能打印出Rr,构造出对象并不一定要进方法,只是调用
专业打酱油
专业打酱油
回复 @白黑白 : 在没有执行Rr的构造方法前,可以执行Rr的t,何解
专业打酱油
专业打酱油
回复 @MZHS : 那如何在R的构造方法中调用R中的t
下一页
0
winnie_tour
winnie_tour
至于n为什么是0的问题,就是成员变量何时初始化的问题了,成员变量只能依靠类的构造器初始化,因为还没执行到Rr的构造器赋值n的语句所以采用了int的默认值。另外,我问lz一个问题:private static int n =1;结果是什么呢?
专业打酱油
专业打酱油
应该是1吧,静态变量也就类变量和成员变量是不同的吧。 静态变量可以没有类的实例,而成员变量必须有一个类的实例才有意义。静态变量会在第一次访问类静态变量或者方法或初始化类实例的时候进行初始化赋值,换句话说,应该在类加载的时候,就赋值了。 而实例变量应该是本类(不包括父类)的构造方法前初始化。
0
序章1984
序章1984
PS. java默认所有函数都是虚函数,会被子类重写。
专业打酱油
专业打酱油
- -!final
返回顶部
顶部