问题背景:下面的代码会输出什么?40还是20?
public class Animal {
public int age=40;
public void eat(){
System.out.println("父类中eat方法");
}
public void show(){
System.out.println("父类中的show方法");
}
}
public class Dog extends Animal {
public int age=20;
public int weight=50;
public void eat(){
System.out.println("子类重写父类中的eat方法");
}
}
public class polymorphismDome {
public static void main(String[] args) {
Animal animal=new Dog();
System.out.println(animal.age);
}
}
先说执行结果是
40
,why?
对于成员属性
规则
1
:
编译阶段是看左边,运行阶段也是看左边
左右就是构造对象时等号两边((Animal animal=new Dog();))的Animal、Dog,
执行看左边输出的就是左边父类中age的值。
如果在编译时左边没有age就会在编译阶段报错(也就是规则中的编译看左边),看下面的例子:
public class Animal {
public void eat(){
System.out.println("父类中eat方法");
}
public void show(){
System.out.println("父类中的show方法");
}
}
public class Dog extends Animal {
public int age=20;
public int weight=50;
public void eat(){
System.out.println("子类重写父类中的eat方法");
}
}
public class polymorphismDome {
public static void main(String[] args) {
Animal animal=new Dog();
System.out.println(animal.age);
}
}
这时idea就会报出这样的错误: 无法解析符号 ‘age’
2.对于非静态成员方法:
规则2:编译看左边,执行看右边。
看例子:
public class Animal {
public void show(){
System.out.println("父类中的show方法");
}
}
public class Dog extends Animal {
public void eat(){
System.out.println("子类重写父类中的eat方法");
}
}
public class polymorphismDome {
public static void main(String[] args) {
Animal animal=new Dog();
animal.eat();
}
}
这个时候再编译阶段就会报错:无法解析符号 ‘eat’(因为编译阶段看的是左边,左边父类中没有eat方法)
在Animal类中添加eat方法后:
public class Animal {
public void eat(){
System.out.println("父类中eat方法");
}
public void show(){
System.out.println("父类中的show方法");
}
}
输出结果为:
子类重写父类中的eat方法
父类和子类中都有eat ,而执行的是右边子类中的eat
那如果左边父类中有eat 方法,而右边子类中没有eat,在执行时会怎么样?会执行错误?不不不,
答案是会执行左边父类中的方法
3.对于静态成员方法:编译看左边,运行也看左边
先看代码:
public class Animal {
public static void speak(){
System.out.println("父类中的静态方法");//
}
}
public class Dog extends Animal {
public static void speak(){
System.out.println("子类中的静态方法");
}
}
public class Main {
public static void main(String[] args) {
Animal animal=new Dog();
animal.speak();
}
}
输出结果为:父类中的静态方法
分析:对于静态方法不存在方法重写这一概念。当子类定义了与父类中static方法同名的方法时,实际上是在子类中定义了一个新的方法,而不是重写父类中的static方法。animal.speak();实际上等价于Animal.speak();在该例子中即使在Dog类中删去speak方法,运行结果也相同,编译也没错。