有A,B两个类,其中B类为A的子类。代码如下:
public class A {
int i = 7;
public A(){
setI(20);
System.out.println("i from a is " + i);
}
public void setI(int i){
this.i = i * 2;
}
}
class B extends A{
int i = 10;
public B(){
System.out.println("i from b is " + i);
}
public void setI(int i){
this.i = i * 3;
}
}初始化一下,答案会是多少呢?
public class Test {
public static void main(String[] args){
new A();
new B();
}
}
显示的答案是:40,7,10.
当删除B类中的int i = 10;之后,答案变成标准的40,60,60.
哪位大佬能帮我解惑下这个变化中的具体过程呢?谢谢!

解决方案 »

  1.   

    对象初始化:在new创建对象时,首先对对象属性和初始化块分配内存,并执行默认初始化。如果存在父类,则先为父类对象属和初始化块先分配内存并执行初始化。然后执行父类构造器中的初始化程序,接着才开始对子类的对象属性和初始化块执行初始化。
      

  2.   

    子类在调用自己的构造方法时,会自动调用其父类的构造方法。你把b类中的i变量注释后,b会从父类a中继承i变量,所以就是60了。
      

  3.   

    感谢,还有一个疑问。
    同样是调用父类构造函数,为何当子类有定义的对象时,setI方法没有起作用,直接打印了i=7呢?
      

  4.   

    60我是明白的,但是7是从何而来呢?
    父类的变量没改变,调用父类构造器时,执行的是子类的setint
      

  5.   

    7  是 a  中的  i
      Debug一下。一步一步往下走。可以知道
      

  6.   

    60我是明白的,但是7是从何而来呢?
    7不就是父类i的值嘛,int i = 7;不过setI走的是b类里的setI,b类重写了a类里的setI方法,所以走b类的setI,i变为了60,不过这既不是父类里的i,也不是子类里的i,而是第三个变量i,所以b类调用a类的构造后,a类i的值还是7,b类有int i-10;了直接输出就是10了。这你懂了吧?
      

  7.   

    60我是明白的,但是7是从何而来呢?
    7不就是父类i的值嘛,int i = 7;不过setI走的是b类里的setI,b类重写了a类里的setI方法,所以走b类的setI,i变为了60,不过这既不是父类里的i,也不是子类里的i,而是第三个变量i,所以b类调用a类的构造后,a类i的值还是7,b类有int i-10;了直接输出就是10了。这你懂了吧?
    说错了,60不是第三个变量,是子类的i。你b类里有int i=10;又重新赋值了。我把int i=10;去掉了 ,晕死,都搞混了。
      

  8.   

    开始不相信,不过试了试的确如此,感谢楼主发现。
    主要是父类,子类问题,7是因为显示的父类值。原因是调用父类构造函数时,seti被子类seti重载,这时运行setI(20)将子类的i写成了60,也就是B.i是60,但A.i由于被重载,不能写入20*2,所以还是7,而父类构造函数打印时不可能打印子类的B.i,而是继续打印A.i,也就是7
      

  9.   


    感谢探讨。指出一个小问题,B.i并没有产生变化,因为下面打印的i from b依然是10……也就是说,从A构造函数自动调用的setI()并没有起任何作用,意即没有改变A.i的值,也没有改变b.i的值,这是为什么呢?
      

  10.   

    60我是明白的,但是7是从何而来呢?
    7不就是父类i的值嘛,int i = 7;不过setI走的是b类里的setI,b类重写了a类里的setI方法,所以走b类的setI,i变为了60,不过这既不是父类里的i,也不是子类里的i,而是第三个变量i,所以b类调用a类的构造后,a类i的值还是7,b类有int i-10;了直接输出就是10了。这你懂了吧?
    说错了,60不是第三个变量,是子类的i。你b类里有int i=10;又重新赋值了。我把int i=10;去掉了 ,晕死,都搞混了。
    感谢回答。但是有个小问题。B.i输出时,即i from b 依然为B类最初赋值int i = 10.
    也就是说,从父类来的setI()没有产生任何作用。i from a 和i from b都是最初的值。
    这是为什么呢?
      

  11.   

    60我是明白的,但是7是从何而来呢?
    7不就是父类i的值嘛,int i = 7;不过setI走的是b类里的setI,b类重写了a类里的setI方法,所以走b类的setI,i变为了60,不过这既不是父类里的i,也不是子类里的i,而是第三个变量i,所以b类调用a类的构造后,a类i的值还是7,b类有int i-10;了直接输出就是10了。这你懂了吧?
    说错了,60不是第三个变量,是子类的i。你b类里有int i=10;又重新赋值了。我把int i=10;去掉了 ,晕死,都搞混了。
    感谢回答。但是有个小问题。B.i输出时,即i from b 依然为B类最初赋值int i = 10.
    也就是说,从父类来的setI()没有产生任何作用。i from a 和i from b都是最初的值。
    这是为什么呢?
    setI()起作用了,作用于子类的i,子类的i被赋值为60,但由于父类构造器初始化在子类变量初始化之前,所以这个值被子类初始化的10覆盖了
      

  12.   

    有一点不明白,如果按照7的输出是因为调用父类构造函数时,seti被子类seti重载,这时运行setI(20)将子类的i写成了60,也就是B.i是60,但A.i由于被重载,不能写入20*2,所以还是7,而父类构造函数打印时不可能打印子类的B.i,而是继续打印A.i,也就是7,那么第二次将int=10去掉后,应该输出变成40 7 60 ,为什么是40 60 60?求问
      

  13.   

    60我是明白的,但是7是从何而来呢?
    7不就是父类i的值嘛,int i = 7;不过setI走的是b类里的setI,b类重写了a类里的setI方法,所以走b类的setI,i变为了60,不过这既不是父类里的i,也不是子类里的i,而是第三个变量i,所以b类调用a类的构造后,a类i的值还是7,b类有int i-10;了直接输出就是10了。这你懂了吧?
    说错了,60不是第三个变量,是子类的i。你b类里有int i=10;又重新赋值了。我把int i=10;去掉了 ,晕死,都搞混了。
    感谢回答。但是有个小问题。B.i输出时,即i from b 依然为B类最初赋值int i = 10.
    也就是说,从父类来的setI()没有产生任何作用。i from a 和i from b都是最初的值。
    这是为什么呢?
    setI()起作用了,作用于子类的i,子类的i被赋值为60,但由于父类构造器初始化在子类变量初始化之前,所以这个值被子类初始化的10覆盖了
    感谢,这点明白了。确实想了解一下jvm的运行方式,请问有推荐的参考资料吗?