多态
1.发生多态的前提:
前提:子类引用父类的对象
2.向上转型
1.定义:
向上转型:父类引用子类对象----》向上转型是子类对象转成父类对象
2.向上转型发生的时机
(1)直接赋值
Animal animal = new Cat(“大花猫”, 19, “man”);
(2)方法传参
(3)方法返回
3.代码示例与图解
class Animal {
public String name;
public int age;
// public Animal() {
// }
static {
System.out.println("Animal::static{}");
}
{
System.out.println("Animal::instance{}");
}
public Animal(String name, int age) {
**eat(); //构造方法内部可以发生多态**
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("Animal: eat()");
}
}
class Cat extends Animal {
public String sex;
static {
System.out.println("cat::static{}");
}
{
System.out.println("cat::instance{}");
}
public Cat(String name, int age, String sex) {
super(name, age);
this.sex = sex;
}
@Override
public void eat() {
System.out.println("Cat :: eat()");
}
public void run() {
System.out.println("Cat :: run()");
}
}
//向上转型
public static void main(String[] args) {
Animal animal = new Cat("大花猫", 19, "man");**//父类引用子类对象**
animal.eat();
}
3.动态绑定
1.定义:
定义:父类引用子类对象,并且父类和子类有同名的覆盖方法;这时,如果通过父类引用调用这个重名方法,就会发生动态绑定。
2.代码示例与图解
class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("Animal: eat()");
}
}
class Cat extends Animal {
public String sex;
public Cat(String name, int age, String sex) {
super(name, age);
this.sex = sex;
}
@Override
public void eat() {
System.out.println("Cat :: eat()");
}
public void run() {
System.out.println("Cat :: run()");
}
}
public static void main(String[] args) {
Animal animal = new Cat("大花猫", 19, "man");//父类引用子类对象
animal.eat();
}
运行结果如下:![在这里插入图片描述](https://img-blog.csdnimg.cn/20191102170019314.png)
4.方法的重写(Override)
1.定义
定义:子类实现父类的同名方法, 并且参数的类型和个数完全相同, 这种情况称为 覆写/重写/覆盖(Override).
2.注意事项
(1)方法名相同、返回值相同(可以不同,但是返回值之间需要构成协变类型)、参数列表相同;
(2)不能在同一个类当中。
(3) 普通方法可以重写, static 修饰的静态方法不能重写。
(4)重写中子类的方法的访问权限不能低于父类的方法访问权限。
(5)重写方法时显式加上 @Override 注解。
5.重写与重载的区别
6.多态的深入理解
1.使用多态的优点
(1)类调用者对类的使用成本进一步降低
(2) 能够降低代码的 “圈复杂度”, 避免使用大量的 if - else
(3)可扩展能力更强
2.对多态的概述
父类引用子类对象,并且父类和子类有同名的覆盖方法;这时,如果通过父类引用调用这个重名方法,就会发生动态绑定。
3.代码示例
class Shape {
public void draw() {
}
}
class Cycle extends Shape {
@Override
public void draw() {
System.out.println("画圆");
}
}
class Rect extends Shape {
@Override
public void draw() {
System.out.println("画矩形");
}
}
public class TestDemo2 {
public static void drawMap(Shape shape) {
shape.draw();
}
public static void main(String[] args) {
Shape shape = new Cycle();
Shape shape1 = new Rect();
drawMap(shape);
drawMap(shape1);
}
}
7.向下转型
1.定义
向下转型就是父类对象转成子类对象;
2.确认向下转型是否安全操作
instanceof 可以判定一个引用是否是某个类的实例. 如果是, 则返回 true. 这时再进行向下转型就比较安全了
class Animal {
public String name;
public int age;
// public Animal() {
// }
static {
System.out.println("Animal::static{}");
}
{
System.out.println("Animal::instance{}");
}
public Animal(String name, int age) {
**eat(); //构造方法内部可以发生多态**
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("Animal: eat()");
}
}
class Cat extends Animal {
public String sex;
static {
System.out.println("cat::static{}");
}
{
System.out.println("cat::instance{}");
}
public Cat(String name, int age, String sex) {
super(name, age);
this.sex = sex;
}
@Override
public void eat() {
System.out.println("Cat :: eat()");
}
public void run() {
System.out.println("Cat :: run()");
}
}
class Bird extends Animal {
public Bird(String name, int age) {
super(name, age);
}
public void fly() {
System.out.println("Bird :: fly()");
}
}
public class TestDemo1 {
public static void main(String[] args) {
Animal animal = new Bird("小鸟", 19);
***//向下转型->一定要发生向上转型->instanceof:***
if (animal instanceof Cat) { ***//cat是否是animal的实例***
Cat cat = (Cat) animal; ***//java.lang.ClassCastException---类型转换异常***
cat.run();
}
}
//向下转型
public static void main(String[] args) {
//向上转型
Animal animal = new Cat("caocao", 19, "man");
//向下转型
Cat cat = (Cat) animal;
cat.run();
}
}
8.super关键字的使用
(1)子类调用父类的方法:super.func();
(2)子类调用父类的属性:super.data;
(3)子类调用父类的构造方法:super();必须放在第一行;
子类的构造,首先需要构造父类;
9.super与this的区别
1.this关键字(还可参考:https://www.cnblogs.com/newbie27/p/10437587.html)
(1.)每个类的每个非静态方法(没有被static修饰)都会隐含一个this关键字,它指向调用这个方法的对象;当在方法中使用本类属性时,都会隐含地使用this关键字,当然也可以明确使用。
this可以看成是一个变量,它的值就是当前对象的引用;
this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用,如果是在同一类中调用另外一个方法,则可以不用写this,直接调用;
(2.)为了区分属性和局部变量,可以通过this关键字来调用;
(3.)this关键字的用法:
当类中非静态方法的参数名与类的某个成员变量名相同时,为了避免参数作用范围覆盖了成员变量的作用范围,必须明确使用this关键字来指定;
如果某个构造方法的第一条语句具有形式this(…),那么这个构造方法将调用本类中的其他构造方法;
如果某个方法需要传入当前对象,则可以将当前的对象作为参数传递给它;
2.super关键字
super代表了父类空间的引用
(1.)super的作用:
子父类存在着同名的成员时,在子类中默认时访问子类的成员,可以通过super关键字指定访问父类的成员;
创建子类对象时,默认会先调用父类无参的构造方法,可以通过super关键字指定调用父类的构造方法;
(2.)super的用法
super可以用来引用直接父类的实例变量。
super可以用来调用直接父类方法。
super()可以用于调用直接父类构造函数
(3.)注意事项:
如果在子类的构造方法上没有指定调用父类的构造方法,java编译器会在子类的构造器里面加上super()语句;
super关键字调用父类的构造函数时,该语句必须要是子类构造函数的第一个语句;
super和this不能同时出现在同一个构造函数中调用其他的构造函数,因为两个语句都要是第一个语句;
3.this和super的区别
(1.)代表的事物不同
super代表的是父类空间的引用;
this代表的是所属函数的调用者对象;
(2.)使用前提不同
super必须要有继承关系才能使用;
this不需要继承关系也能使用;
(3.)调用的构造函数不同
super:调用父类的构造函数;
this:调用所属类的构造函数;