1、因为method3()是子类中的方法,而你定义的f是父类的引用,只是指向了子类对象。f能调用的只能是在父类中定义过的方法。所以不能直接调用。只有先向下转型,然后才能调用。
2、毕老师在视频中说的,在多态中编译看左边,运行看右边的意思是你在建立子类对象,用该对象调用方法。在编译时就会检查,你所调用的这个方法是否在父类中存在。就如你的这个程序你是 Fu f = new Zi();.你建立的是子类对象但是是父类的引用。如果你调用的方法在父类中没有定义,编译时就会报错。但是在执行的时候,因为父类没有建立对象,建立的是子类对象,执行的内容还是子类中的内容。
具体的请看代码:
这里有段代码,都你理解this和super有帮助,注释不是很多,但相信你一定很看得懂,一定会有所收获的!作者: 樊玲 时间: 2013-3-16 12:35
class Fu
{
static int num = 5;//多态中成员变量,面试中常见,开发中不常见
void method1()
{
System.out.println("fu method_1");
}
void method2()
{
System.out.println("fu method_2");
}
static void method4()//多态中静态成员函数,面试中常见,开发中不常见
{
System.out.println("fu method_4");
}
}
class Zi extends Fu
{
static int num = 8;//多态中成员变量,面试中常见,开发中不常见
void method1()
{
System.out.println("zi method_1");
}
void method3()
{
System.out.println("zi method_3");
}
static void method4()//多态中静态成员函数,面试中常见,开发中不常见
{
System.out.println("zi method_4");
}
}
class DuoTaiDemo4
{
public static void main(String[] args)
{/*
Fu f = new Zi();
System.out.println(f.num);//5
Zi z = new Zi(); 静态成员函数和成员变量的特点:
System.out.println(z.num);//8 无论编译和运行,都参考做左边
f.method4();//fu method_4
z.method4();//Zi method_4 注意:面试中常见,开发中不常见*/
//开发中常见,因为子类可以复写父类,提高程序的扩展性
Fu f = new Zi();
f.method1();//zi method_1
f.method2();//fu method_2
if (f instanceof Zi)
{
Zi z=(Zi)f; //向下转型
z.method3();
}
// f.method3();//编译不通过,因为成员函数在多态调用时,编译看左边,运行看右边//(<FONT color=red>1)如果我想在多态中运行method3()方法,该怎么改代码啊?
}
}
注:这里Fu f=new Zi();为父类引用,指向子类对象。如果想用子类中的特有方法,method3,就必须向下转型,
将f 转成Zi类类型的。并进行instanceof 判断(看f引用的真实类型 )。这样才能调用子类的特有方法。作者: 吴林飞 时间: 2013-3-16 18:04 本帖最后由 吴林飞 于 2013-3-16 20:47 编辑
你可以看看我提供的附件,那是我对多态中成员的特点的总结。
1 先说说多态中出现同名成员变量的问题:
class Fu {
int num = 5;
}
class Zi extends Fu{
int num = 8;
}
class Test2{
public static void main(String[] args){
Fu f = new Zi();
System.out.println(f.num); //输出: 5
}
编译时期:没什么可说的,和多态中出现成员函数的情况一样,都是参考左边,也就是引用型变量所属的类,因为这时候对象还未产生,所以JVM其实检查的是引用型变量所属的类,如果这个类中定义了该引用所调用的变量,则编译通过,如果没有定义则编译失败。
运行时期:Fu f = new Zi();
System.out.println(f.num);
首先通过new在堆内存中产生了一个子类对象,这个对象中有两个变量,一个是父类的变量,一个是子类的变量(因为在运行时期,当new子类对象时,JVM发现子类继承了父类,所以先加载了父类中的变量进内存)。所以当通过父类引用f调用num输出时,输出的是父类中定义的num的值。
2 再说说多态中出现同名函数的问题:
编译时期:无论是静态或非静态,都参考左边,也就是引用型变量所属的类,因为这时候对象还未产生,所以JVM其实检查的是引用型变量所属的类,如果引用型变量所属的类中有这个变量所调用的方法,则编译通过。如果没有,则编译失败。
运行时期:
如果是非静态
参阅对象所属的类中是否有调用的方法
因为父类的引用指向了子类对象,在内存中其实是子类对象在对非静态方法区中的非静态方法进行操作。
如果是静态
参阅引用型变量所属的类中是否有调用的方法
因为是静态,所以和对象没有关系,而是随着类走,这时候其实是在内存中的静态方法区中通过类名直接调用方法。
所以,如果想要运行method3()方法,可以将method3方法用static修饰,变成静态方法,因为当method3()被静态修饰以后,method3方法就静态绑定在了方法区中的静态区,这时候method3方法是随着类走的,可以直接通过类名调用。如下代码所示:
class Fu {
static void method3(){
System.out.println("fu method_3");
}
}
class Zi extends Fu{
static void method3(){
System.out.println("zi method_3");
}
}
class Test2{
public static void main(String[] args){
Fu f = new Zi();
f.method3(); //输出:fu method_3
Zi z = new Zi();
z.method3(); //输出:zi method_3
}
}