class Base
{
int i=99;
public void amethod()
{
System.out.println("llll");
}
}
public class GaiSJK extends Base
{
int i=988;
int c=2;
public static void main(String arg[])
{
Base a= new GaiSJK();
System.out.println(a.i);
a.amethod();
} public void amethod()
{
System.out.println("ssss");
}
} 为什么a调用的方法是子类的,而变量却是父类的?
请高手详解,越详细越好,谢谢!!
{
int i=99;
public void amethod()
{
System.out.println("llll");
}
}
public class GaiSJK extends Base
{
int i=988;
int c=2;
public static void main(String arg[])
{
Base a= new GaiSJK();
System.out.println(a.i);
a.amethod();
} public void amethod()
{
System.out.println("ssss");
}
} 为什么a调用的方法是子类的,而变量却是父类的?
请高手详解,越详细越好,谢谢!!
1、将代码作良好的格式化,以方便阅读。
2、在发帖文本框的上方单击“#”按钮,选择 Java
3、将代码粘贴到【code=Java】和【/code】之间。发出来的帖子就会是下面的效果:public class Hello { // 程序入口
public static void main(String[] args) {
System.out.println("Hello!");
}
}
GaiSJK的amethod()覆盖Base的amethod(),你定义的对象是new GaiSJK(); ,那么在调用方法的时候,调用的是子类的GaiSJK.amethod();如果调用的是成员变量的时候,则是根据你的引用(Base a)来调用成员变量,此时你的引用是Baer。
这是因为,1、你的引用是Base,base.amethod()不存在;2、父类的引用Base 不能跨越自己的权限,去访问子类的方法
所以,用父类的引用指向子类的对象,在父类的引用调用方法时,父类必须实现该方法,调用的什么,如果子类覆盖了父类的方法,则调用子类的方法,如果没有覆盖,则调用自身(父类)的方法
GaiSJK 在继承Base的时候,重写了方法amethod(),这个信息将在Method Table中反映,所以你在把GaiSJK 对象实例转换成Base类型后,方法表并未改变,所以调用的是之类的方法。但是由于属性a在父类和子类的数据结构中都各自占有空间,所以调用的是父类的属性。不知道这样解释对不对
因为这是多态中的向上转型,也就是说虽然你申明的是 Base a,但是却是new 的子类GaiSJK,这样的话用C++里的话说就是指针指向的是子类的地址,所以理所当然应该是调用子类的方法(前提是子类覆盖掉父类的方法),如果没有覆盖,就会调用父类的方法,因为继承本身就是把父类的方法再重用一遍了。
java中的多态是方法的多态,而不是字段的多态当GaiSJK继承Base时
方法amethod()被override
但字段i并没有被覆盖,而是保留一个副本存在子类GaiSJK中
也就是说子类GaiSJK的amethod()是自己的,以区别于他的父类
而字段i有两个,一个是自己的,还有一个是他爸爸给的
如果GaiSJK还有更深层次的祖先类,并且每个类都定义了字段i
那GaiSJK就有来自所有继承类的字段i的副本Base a= new GaiSJK();
这时候a这个引用指向的是子类的对象
a.amethod(); 调用的肯定是子类的方法
这就是多态,这是毫无疑问的
a.i中由于a是父类引用,并且在GaiSJK中有父类字段i的值
所以a.i得到是父类的值,而不是子类的值
内存空间中,子类对象空间中包含个父类对象,类对象中好似有个指针指向代码区中要执行的方法代码(code),java的多态机制规定这个指针要根据实际new出来的对象来决定指向谁的方法code.本例中,父类Base引用a1指向了子类GaiSJK对象,给a1 new出来的是GaiSJK对象,所以在a1.amethod()调用的是子类的;我们又注意到,在内存中new GaiSJK()出来的对象和其中包含的父类对象都含有i属性,但是对于a1可见的只有父类中的i,所以在调用时就是父类的