class Base {
// 定义了一个名为i的实例变量
private int i = 2; public Base() {
this.display();
} public void display() {
System.out.println(i);
}
}// 继承Base的Derived子类
class Derived extends Base {
// 定义了一个名为i的实例变量
private int i = 22; // 构造器,将实例变量i初始化为222
public Derived() {
i = 222;
} public void display() {
System.out.println(i);
}
}public class Test {
public static void main(String[] args) {
// 创建Derived的构造器创建实例
new Derived();
}
}运行结果是:0
求大牛解释一下原理。
// 定义了一个名为i的实例变量
private int i = 2; public Base() {
this.display();
} public void display() {
System.out.println(i);
}
}// 继承Base的Derived子类
class Derived extends Base {
// 定义了一个名为i的实例变量
private int i = 22; // 构造器,将实例变量i初始化为222
public Derived() {
i = 222;
} public void display() {
System.out.println(i);
}
}public class Test {
public static void main(String[] args) {
// 创建Derived的构造器创建实例
new Derived();
}
}运行结果是:0
求大牛解释一下原理。
// 定义了一个名为i的实例变量
private int i = 2;
public Base() {
System.out.println("Base中:"+i);
this.display();
}
public void display() {
System.out.println("Base中dis:"+i);
System.out.println("我被多态了啊"+i);
}
}
// 继承Base的Derived子类
class Derived extends Base {
// 定义了一个名为i的实例变量
private int i = 22;
// 构造器,将实例变量i初始化为222
public Derived() {
System.out.println("Derived中:"+i);
i = 222;
}
public void display() {
System.out.println("Derived中dis:"+i);
System.out.println("是我吗?"+i);
}
}
public class Test {
public static void main(String[] args) {
// 创建Derived的构造器创建实例
new Derived();
}
}运行结果是:
Base中:2
Derived中dis:0
是我吗?0
Derived中:22
加了几个输出会好看一点
我的理解是 new Derived();时候会递归调用父类构造方法,父类的构造方法又调用了子类的display()方法,这时候的i还是0吧,不很清楚为什么是0,大神指点吧...共同学习,输出的就是子类的那个display()方法的i
debug的时候出现了两个i,一个是属性的一个等于0的就看到这些了....
此时,程序是这样走的:
1.进入Derived的构造方法: public Derived() {
super();//这里隐含一个调用父类构造的语句。
i = 222;
}2.通过super()方法进入Base类的构造方法: public Base() {
this.display();//因为多态的原故,这句会调用子类覆写的方法
}3.调用Derived类的display()方法: public void display() {
System.out.println(i);//此时,变量i还未被赋值,默认初始值是0,因此输出0
}4.第三步执行完后,再继续执行Derived构造方法里的下一句:i = 222;//虽然变量i被赋值了,可是输出语句已经完成了。5.程序执行完毕.
我刚开始也做错了,后来自己更改不同的条件测试了7,8次吧。也就懂了。
首先,加上
System.out.println("derived display:"+i);
System.out.println("base display:"+i);
输出的是derived display:0,知道调用的是子类的方法。父类的方法被子类重写了。
然后
private int k=22;
public Derived(){
k=222;
}
public void display(){
System.out.println("derived display:"+i);
}
把Derived的i改成k,这时候输出i报错,也就说明其实没有i这个量。如果非要输出,只能输出0或者报错。然后再把Base的i改成Public,这时候输出2。
这时候就说明是这道题做的功能实际上就是把子类的display方法代替了父类的那个display方法。
剩下的就容易理解了吧?
// 定义了一个名为i的实例变量
private int i = 2;
public Base()
{
System.out.println("父类的构造方法");
this.display();
}
public void display()
{
System.out.println("父类的具体方法");
System.out.println(i);
}
}
// 继承Base的Derived子类
class Derived extends Base
{
// 定义了一个名为i的实例变量
private int i = 22;
// 构造器,将实例变量i初始化为222
public Derived()
{
System.out.println("子类的构造方法");
i = 222;
}
public void display()
{
System.out.println("子类的具体方法");
System.out.println(i);
}
}
public class Test12
{
public static void main(String[] args)
{
// 创建Derived的构造器创建实例
new Derived();
}
}
Derived继承了Base类,因此在new Derived();实例化的过程中,通过new关键字调用无参的构造方法(),Derived继承了Base类,Derived类先加载在JVM上,然后实例化生成对象,通过这个对象,会先调用父类的无参构造方法,然后再执行调用子类的构造方法
然后初始化 参数列表中的变量(如果有),然后才执行其他语句。
这是一个典型的有继承关系的类的初始化顺序问题。原理其实楼上有几位已经说得比较清楚了,下面我们来就题论题一下:首先从main方法开始,new Derived()就是要new一个Derived的对象,那么根据对象初始化的顺序,
初始化子类Derived之前必须要初始化父类Base,那么由于在调用构造函数之前,成员变量是先于构造函数初始化的,这个时候Base里面的i已经有值了,是2。在Base构造函数里面, 只有一句:this.display(), 这个方法在Base的子类Derived也定义了,并且此次初始 化是由子类Derived发起的,所以实际上这个方法调用的是Derived里面定义的display,而不是Base自己的display(所以输出不是2)。
而这个时候子类Derived还没有进行构造,因为此时父类Base才正在构造之中,所以子类Derived中的i还是0,而display正好打印出的是子类Derived的i,所以最后的输出是0.不知道能解释的清楚楼主的问题么?
我实测了一下,输出结果是输出2!
1。《java核心技术卷1-基础知识》中说在使用new关键字实例化对象时,类的域(类的成员)会先于构造器被实例化。我实测了下,父类和子类的域会被几乎同时实例化,域实例化后的值是默认值。
2.我实测了下,代码中对类的域的赋值语句会在构造器启动之后,但是在开始执行方法块中的第一条语句之前执行。
3.子类的构造器在启动之后会先启动父类的构造器。(我知道“启动”这个词可能不够专业,但是我也不知道怎么描述。看的人懂就好。)
4.this关键字是指向实例的引用。
上面四点就可以解释这个测试类的输出结果了。