Java访问子类对象的实例变量
对于Java这种语言来说,一般来说,子类可以调用父类中的非private变量,但在一些特殊情况下,
Java语言可以通过父类调用子类的变量
具体的还是请按下面的例子吧!
package com.yonyou.test; /** * 测试类 * @author 小浩 * @创建日期 2015-3-2 */ class Base { // 定义了一个名为i的实例变量 private int i = 2; public Base() { this.display(); //注意这里面的this代表当前正在运行的对象,即Derived对象 } 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,是不是很意外,这里你需要明白。
public Base() { this.display(); //注意这里面的this代表当前正在运行的对象,即Derived对象 }
这里面的this指的是当前正在运行的那个对象,那么当前运行的对象是谁?没错,就是Derived对象。
为了确定是Derived,我们可以看下面的代码:
public Base() { System.out.println(this.i); //新增加的变量 其值为2 this.display(); //注意这里面的this代表当前正在运行的对象,即Derived对象 System.out.println(this.getClass()); } //最后结果为:
// 2 // 0 // class com.yonyou.test.Derived
但是现在的问题又出现了如果修改上面的代码加入System.out.println(this.i)
如下面的例子:
public Base() { System.out.println(this.i); //新增加的变量 其值为2 this.display(); //注意这里面的this代表当前正在运行的对象,即Derived对象 }
既然这俩this的指的是Derived对象,那为什么其值不是0,而是父类Base对象里面对应变量
的值2呢?
这里涉及到了编译类型和运行时类型相关的内容。当变量的编译类型和运行时类型不同的话,通过该对象访问其所引用对象的实例变量的时候
表现出该实例变量所声明时的类型决定。因为
System.out.println(this.i); //新增加的变量 其值为2
这里的this访问的变量,所以其值为声明它的对象Base的值,即2
但通过通过此实例变量调用它所对应的实例方法的时候,该方法的行为将由它实际所引用的对象来决定。
因为
this.display(); //注意这里面的this代表当前正在运行的对象,即Derived对象
这里的this的实际引用它的对象为Derived,所以其i值为0.
根据java创建对象时初始化对象的时机(http://www.cnblogs.com/xiohao/p/4349833.html),我们知道这时Derived中的变量i还没有初始化,
所以最后的结果为:0
最后提示一下如果是静态方法的话,仅仅序声明它的类型相关,与其它的没有任何关系哦...
下面是对比的例子:
1 静态方法,仅仅与其声明的类型有关
package com.yonyou.test; /** * 测试类 * @author 小浩 * @创建日期 2015-3-20 */ public class Test { public static void main(String[] args) { Base b=new Base(); Base c=new Inherit(); b.a(); b.b(); c.a(); c.b(); } } class Base{ static void a( ){System.out.println("A"); } void b( ){System.out.println("B"); } } class Inherit extends Base{ static void a( ){System.out.println("C"); } void b( ){System.out.println("D"); } }
最后的结果为:A,B,A,D
2.非静态方法正常,与其真正所引用的类型相关
package com.yonyou.test; /** * 测试类 * @author 小浩 * @创建日期 2015-3-20 */ public class Test { public static void main(String[] args) { Base b=new Base(); Base c=new Inherit(); b.a(); b.b(); c.a(); c.b(); } } class Base{ void a( ){System.out.println("A"); } void b( ){System.out.println("B"); } } class Inherit extends Base{ void a( ){System.out.println("C"); } void b( ){System.out.println("D"); } }
结果为:A,B,C,D
上面的话有一些绕,请务必多读几遍,反复揣摩,这样你会更上一层楼。
如果实在不懂也可以发送邮件至:12612455595@qq.com
如果你确实理解了的话,请通过下面的例子测试一下:
package com.yonyou.test; /** * 测试类 * @author 小浩 * @创建日期 2015-3-2 */ class Animal { // desc实例变量保存对象toString方法的返回值 private String desc; public Animal() { // 调用getDesc()方法初始化desc实例变量 this.desc = getDesc(); //② } public String getDesc() { return "Animal"; } public String toString() { return desc; } } public class Wolf extends Animal { // 定义name、weight两个实例变量 private String name; private double weight; public Wolf(String name , double weight) { // 为name、weight两个实例变量赋值 this.name = name; //③ this.weight = weight; } // 重写父类的getDesc()方法 @Override public String getDesc() { return "Wolf[name=" + name + " , weight=" + weight + "]"; } public static void main(String[] args) { System.out.println(new Wolf("灰太狼" , 32.3)); //① } }
提示:最后的结果为:
Wolf[name=null , weight=0.0]
测试例子2:
class Base { int count = 2; public void display() { System.out.println(this.count); } } class Derived extends Base { int count = 20; @Override public void display() { System.out.println(this.count); } } public class FieldAndMethodTest { public static void main(String[] args) { // 声明、创建一个Base对象 Base b = new Base(); //① // 直接访问count实例变量和通过display访问count实例变量 System.out.println(b.count); b.display(); // 声明、并创建一个Derived对象 Derived d = new Derived(); //② // 直接访问count实例变量和通过display访问count实例变量 System.out.println(d.count); d.display(); // 声明一个Base变量,并将Derived对象赋给该变量 Base bd = new Derived(); //③ // 直接访问count实例变量和通过display访问count实例变量 System.out.println(bd.count); bd.display(); // 让d2b变量指向原d变量所指向的Dervied对象 Base d2b = d; //④ // 访问d2b所指对象的count实例变量 System.out.println(d2b.count); } }
运行结果为:
2 2 20 20 2 20 2
好吧,今天就先到这里吧、、、