父类的引用指向子类的对象:
Fu obj = new Zi();int num = obj.num;obj.show();obj.methodZi();
1.如果父类和子类都有成员变量num
,请问上面的例子中访问的是谁的成员变量?
答:看等号左边是谁(变量的声明类型),则优先用谁的,没有则向上。所以访问的是父类的成员变量num
。父类的变量是不能被子类覆盖重写的
2.如果父类和子类都有成员方法show()
,请问上面的例子中访问的是谁的成员方法show()
?
答:看等号右边是谁(创建哪个类的实例对象,即对象实际所属的类型),则优先调用谁的,没有则向上。子类有show()
,所以就是调用子类的,没有就向上在父类中查找。父类的成员方法可以被子类覆盖重写
3.子类有方法methodZi()
,但是父类没有,那么通过变量名称调用方法methodZi()
是否正确呢?
答:错误。Java 代码在编译的时,对于引用类型的变量,编译时看的是声明的类型,运行时才看对象的实际类型。变量 obj 声明的类型是父类,父类根本没有方法methodZi()
,所以obj.methodZi();
编译会报错。为什么obj.show();
不会报错,因为父类也有show()
方法所以编译不会报错,但是在运行时看的是右边,右边的子类也有方法show()
,所以实际调用的是子类的方法show()
口诀:
对于成员方法:编译看左边,运行看右边。
对于变量:编译看左边,运行也看左边。
多态的好处:
可以创建各种子类对象,都不会影响父类变量的方法调用代码,因为父类变量是根据父类所声明的方法进行调用的。
注意下面的错误代码:
FuInterface obj = new FuInterfaceImpl();obj.staticMethod(); // 编译直接报错,提示:只有含有此静态方法的接口类才能调用此静态方法
注:staticMethod() 是接口和实现类都有的静态方法
但是下面的代码没有错误:
Fu obj = new Zi();obj.staticMethod(); // 编译通过,而且只会调用父类的静态方法
注:
1.staticMethod() 是父类和子类都有的静态方法
2.子类不能覆盖重写父类的静态方法,但是子类也可以声明定义和父类一模一样的静态方法,但不属于覆盖重写