你或许不知道——在极端情况上,父类访问子类变量所存在的有关问题
你或许不知道——在极端情况下,父类访问子类变量所存在的问题
程序清单:
package com.yjk;
public class Parent
{
//定义一个名为i的实例变量
private int i = 1;
public Parent()
{
this.display();
}
public void display()
{
System.out.println(i);
}
}
---------------------------------
public class Son extends Parent
{
//定义一个名为i的实例变量
private int i = 2;
//构造器,将实例变量i初始化为3
public Son()
{
i = 3; //⑵
}
public void display()
{
System.out.println(i);
}
}
---------------------------------
package com.yjk;
public class Test {
public static void main(String[] args)
{
//创建子类实例
new Son(); //⑴
}
}
}
---------------------------------
这行代码会调用子类Son里的构造器,由于子类Son继承了父类Parent,而且子类Son的构造器中,并没有显示的使用Super
调用父类Parent的构造器,因此系统会自动调用Parent类中的无参构造器来执行初始化。
在父类Parent的无参构造器中,只是调用了display方法来向控制台输出变量i的值,但是结果却为0。
OK,那么到此,如果你知道是为什么,就可以略过以下内容,反之,请耐心的滚动你的鼠标:
当程序运行至1处时,系统为Son实例对象分配了两块内存空间,是的,换言之就是说,Son对象拥有2个名为i的实例变量
声明:
永远记住,构造起只负责对 实例对象的变量进行赋值 ,别无它用。构造器不是用来创建对象的,不是,真的不是!
其实在构造器执行之前,系统已经为该对象分派好内存了,此时此刻,内存中的所有变量值都为默认值,比
如:0,false,null.
言归正传,系统为Son对象分配了2块内存,分别用于存放变量i,其中一个属于Parent类定义的i实例变量,另一个属于
Son类定义的i实例变量,此时此刻,二者的值都为0;
接下来,便是先执行父类的构造器对其值进行赋值操作。Parent中定义i的时候便对其进行了初始化操作,且值为1.接着便
执行display()操作,OK,问题来了人,该方法this.diaplay() 中的this 是谁?对,此时还是不够混乱,OK,我们对Parent做
一点小修改:
package com.yjk;
public class Parent
{
//定义一个名为i的实例变量
private int i = 1;
public Parent()
{
System.out.println(this.i);
this.display();
}
public void display()
{
System.out.println(i);
}
}
再次运行,我们可以得到1,0;此刻是不是觉得更加混乱了?
揭秘:
当this在构造器中出现的时候,它所代表的正是当前初始化的实例对象,此时的this位于Son的构造方法中,但是代码们
却出现在父类Parent的构造方法中,那么系统便在Son构造器中,隐式的调用父类Parent构造器中的代码,故,此时的this
是Son对象,既然如此,它输出的却是父类对象的值,这是因为该行代码位于Parent类型中的构造器中,故其编译类型是
Parent,而它实际引用Son了对象.
下面对其进一步进行解释:
package com.yjk;
public class Parent
{
//定义一个名为i的实例变量
private int i = 1;
public Parent()
{
System.out.println(this.i);
this.display();
System.out.println(this.getClass());
}
public void display()
{
System.out.println(i);
}
}
---------------------------------
“
当变量的编译时的类型和运行时的类型不同时,通过该变量访问它引用的对象的实例变量时,该实例变量的值由声明该
变量的类型决定。但通过该变量调用它引用的对象的实例方法时,该方法行为将由它实际引用的对象来决定。因此,当
程序访问this.i时,将会访问Parent类中定义的i实例变量,也就是输出1;但执行this.display()方法时,则实际表现出Son对
象的行为,也就是输出Son对象的实例变量,即 0.
”—李刚
看一次可能不能完全接受,多看即便就好了,最后,希望这个帖子能够为你带来一定的收获。
程序清单:
package com.yjk;
public class Parent
{
//定义一个名为i的实例变量
private int i = 1;
public Parent()
{
this.display();
}
public void display()
{
System.out.println(i);
}
}
---------------------------------
public class Son extends Parent
{
//定义一个名为i的实例变量
private int i = 2;
//构造器,将实例变量i初始化为3
public Son()
{
i = 3; //⑵
}
public void display()
{
System.out.println(i);
}
}
---------------------------------
package com.yjk;
public class Test {
public static void main(String[] args)
{
//创建子类实例
new Son(); //⑴
}
}
}
---------------------------------
这行代码会调用子类Son里的构造器,由于子类Son继承了父类Parent,而且子类Son的构造器中,并没有显示的使用Super
调用父类Parent的构造器,因此系统会自动调用Parent类中的无参构造器来执行初始化。
在父类Parent的无参构造器中,只是调用了display方法来向控制台输出变量i的值,但是结果却为0。
OK,那么到此,如果你知道是为什么,就可以略过以下内容,反之,请耐心的滚动你的鼠标:
当程序运行至1处时,系统为Son实例对象分配了两块内存空间,是的,换言之就是说,Son对象拥有2个名为i的实例变量
声明:
永远记住,构造起只负责对 实例对象的变量进行赋值 ,别无它用。构造器不是用来创建对象的,不是,真的不是!
其实在构造器执行之前,系统已经为该对象分派好内存了,此时此刻,内存中的所有变量值都为默认值,比
如:0,false,null.
言归正传,系统为Son对象分配了2块内存,分别用于存放变量i,其中一个属于Parent类定义的i实例变量,另一个属于
Son类定义的i实例变量,此时此刻,二者的值都为0;
接下来,便是先执行父类的构造器对其值进行赋值操作。Parent中定义i的时候便对其进行了初始化操作,且值为1.接着便
执行display()操作,OK,问题来了人,该方法this.diaplay() 中的this 是谁?对,此时还是不够混乱,OK,我们对Parent做
一点小修改:
package com.yjk;
public class Parent
{
//定义一个名为i的实例变量
private int i = 1;
public Parent()
{
System.out.println(this.i);
this.display();
}
public void display()
{
System.out.println(i);
}
}
再次运行,我们可以得到1,0;此刻是不是觉得更加混乱了?
揭秘:
当this在构造器中出现的时候,它所代表的正是当前初始化的实例对象,此时的this位于Son的构造方法中,但是代码们
却出现在父类Parent的构造方法中,那么系统便在Son构造器中,隐式的调用父类Parent构造器中的代码,故,此时的this
是Son对象,既然如此,它输出的却是父类对象的值,这是因为该行代码位于Parent类型中的构造器中,故其编译类型是
Parent,而它实际引用Son了对象.
下面对其进一步进行解释:
package com.yjk;
public class Parent
{
//定义一个名为i的实例变量
private int i = 1;
public Parent()
{
System.out.println(this.i);
this.display();
System.out.println(this.getClass());
}
public void display()
{
System.out.println(i);
}
}
---------------------------------
“
当变量的编译时的类型和运行时的类型不同时,通过该变量访问它引用的对象的实例变量时,该实例变量的值由声明该
变量的类型决定。但通过该变量调用它引用的对象的实例方法时,该方法行为将由它实际引用的对象来决定。因此,当
程序访问this.i时,将会访问Parent类中定义的i实例变量,也就是输出1;但执行this.display()方法时,则实际表现出Son对
象的行为,也就是输出Son对象的实例变量,即 0.
”—李刚
看一次可能不能完全接受,多看即便就好了,最后,希望这个帖子能够为你带来一定的收获。