最近重新学习Java基础,有许多以前不知道的地方。随手记录下来,主要面向自己,能帮助到别人当然更好,如有错误和不足,还望指正。
多态的场景
- 有继承关系
- 有子类对父类方法的重写
- 父类的应用指向子类对象
class Person{
}
class Student extends Person{}
public class MyTest {
public static void main(String[] args) {
Person a = new Student();
}
}
口诀
1. 成员变量:
编译看左边,运行看左边
//父类
class Animal{
private String name = "ergo";
public int age = 10;
public Animal() {}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
//非静态成员方法
public void show() {
System.out.println("----父类非静态方法----");
}
//静态成员方法
public static void func() {
System.out.println("----父类静态方法----");
}
}
//子类
class Dog extends Animal{
private String color = "红色";
public int size = 20;
public void play() {
System.out.println("play");
}
//重写父类show()方法
@Override
public void show() {
System.out.println("子类重写父类的非静态方法");
}
public static void func() {
System.out.println("子类静态方法");
}
}
public class Demo {
public static void main(String[] args) {
Animal dog = new Dog();
//编译通过,因为父类有age属性
System.out.println(dog.age);
//编译不通过,因为父类没有size属性
//System.out.println(dog.size);
}
}
10
可以看出,对于成员变量,不管是编译还是运行,都依据父类的。
2. 成员方法:
编译看左边,运行看右边
在上面的代码中,我们在Dog类中重写了Animal类的非静态方法show(),还添加了子类独有的方法play()。接下来用创建的对象来调用这些方法观察下结果。
public class Demo {
public static void main(String[] args) {
Animal dog = new Dog();
dog.show();
//报错,因为父类中没有play()方法。
//dog.play();
}
}
子类重写父类的非静态方法
由于父类中没有play()方法,所以dog.play()语句不能通过编译;而子类重写了父类的show(),执行的其实是子类重写后的show()方法。这也是为什么说重写是多态的前提之一。
3. 静态方法:
编译看左边,运行看左边
严格意义上来说,对静态方法并不能算重写,因为“重写”只适用于实例方法,而静态方法是属于类的,并不需要实例化对象去调用,不实例化也就不存在多态了。所以虽然形式上是重写的写法,但并不能达到重写的效果。