public class test{
public static void main(String args[]){
A a= new B();
System.out.println(a.var);
System.out.println(a.f());
}
}
class A {
int var =1;
int f(){
return var ;
}
}
class B extends A {
int var =2;
int f(){
return var ;
}
}
请问为什么a.var =1,而a.f()=2。a指向子类对象的引用,调用的方法是子类的方法,为什么调用的成员变量却是父类的,请解惑。谢谢。
[b]问题补充:[/b]
第一次发贴,居然没找到地方可以回复。请指点怎样才能回复自己的帖子。
“
属性的值取父类还是子类并不取决于我们创建对象的类型,而是取决于我们定义的变量的类型”
我也知道是这样子的,但不知道原因所以就来这问了。
[size=medium]不知道楼主对this有了解多少[/size]
[code="java"]System.out.println(a.var);[/code]
[size=medium]这个不用说啦吧,是指向父类的引用,所以打印出来的就是父类的var的值[/size]
[code="java"]System.out.println(a.f());[/code]
[size=medium]这个虽然类型是A但是,是用B的构造方法初始化的,所以引用指向B
在B中的方法是这样的[/size]
[code="java"]int f() {
return var;
}[/code]
改写下会更清晰的
[code="java"]
int f() {
return this.var;
}[/code]
[size=medium]其实jvm也是这么做的,因为引用指向的就是子类B所以打印出来的就是B中var的值[/size]
ps:
不知道这么说楼主明白否~呵呵,不明白可以短消息我哦~ :o
楼主应该仔细研究一下这篇博文:
[url=http://zangweiren.iteye.com/blog/211278]JAVA面试题解惑系列(三)——变量(属性)的覆盖[/url]
不要漏掉下面的回复.
:x 不知道二楼aidiyuxin说的是什么!!!
请教一楼
你给的帖子里用事实证明了一个问题
[quote]属性的值取父类还是子类并不取决于我们创建对象的类型,而是取决于我们定义的变量的类型[/quote]
但是没有解释为什么java这样处理,这样做应该是有某种目的的,并且有官方文档说明。之所以这样说是因为:
当A a=new B();后a的f方法是创建类B的,但a的var成员变量却是A的,直观感觉比较诡异。
请解答谢谢!
抱歉我没地方发就发答案中了
说白了, 就是方法可以Override, 但是成员变量不能.楼主加一条输出:
[code="java"]System.out.println(((B) a).var);[/code], 会发现输出的是2, 也就是说子类和父类各维护自己的一圈成员变量.
当一个对象被实例化的时候,它的父类也会被实例化,递推...此时在堆区中就存在该对象以及该对象的所有父类的实例化了.实例化其实是对对象的成员变量的初始化.至于方法,在下面说.
在对象中有个隐藏的属性super指向它的父类的对象,还有个隐藏的this指向对象自己.
a.var实际取出的是a对象的属性.
而方法,在类被加载的时候就已经被加载到了方法区中了,一个类的所有对象都持有相同的方法指针.在java中,所有的方法都是虚方法,也就是说方法都是动态匹配的,若在子类中找到了fun方法,它就执行子类的,若没找打继续区父类中找...,而类的所有实例方法,在执行的时候(也就是虚拟机执行它的时候),会把this和super两个属性也压入方法栈中,若在方法的局部变量中找不到变量var,则就会区this对象中找.
当执行a.fun()时,其实放回的是this的var属性,而此this就是类B的对象,所以拿到的是2.
来晚了,呵呵
顶这个
改写下会更清晰的
Java代码 复制代码
[code="java"] int f() {
return this.var;
} [/code]
楼主记住一点就明白了。书上应该有提到的。
多态只针对方法,不针对属性的。。。。