Java--多态和抽象类

多态

在Java中多态就是在完成一件事的时候,不同人去完成产生的结果不同
比方说打印,我们就是要打印一个东西,如果我们交给彩色打印机,那么会打印出来彩色的,而交给黑白打印机的话则会打印出来黑白的。

实现多态的条件

  1. 有继承关系
  2. 子类会重写父类的方法
  3. 会发生向上转型
    在Java中的体现则是,当代码运行时,传递不同的类对象时返回的结果不同。

重写

重写(覆盖),子类对父类非静态,非private,非final的方法的核心部分进行重新编写

  1. 重写时,方法名字不可以变,返回类型不可以改变,参数列表不可以改变。只可以更改核心部分的代码。
  2. 对于修饰方法的修饰符可以有变化,但是就是子类的访问权限不能低于父类的访问权限。
  3. 返回类型也可以修改,只不过需要构成父子类关系,如下:父类中的返回值类型为A,子类的返回值类型为B,两者构成了父子关系,所以可以修改返回类型。
class A {
    public A eat() {
        return new A();
    }
}
class B extends A {
    @Override
    public B eat() {
        return new B();
    }
}
  1. 我们可以在重写方法的时候,在方法上加上注解@Override,这个注解的作用就是帮助我们检查,我们方法名写没写错等。

重写和重载

这个知识点也经常被作为面试题,当然很多学校也很喜欢考,在以前的文章中介绍过重载,在这就不过说了。
在这里插入图片描述

重载是在一个类中呈现多态性
重写是在父类和子类继承的时候呈现多态性

静态绑定和动态绑定

静态绑定:也可以称为前期绑定(早绑定),在编译的时候,根据用户传递的参数来确定调用哪个方法。(方法重载就是典型的静态绑定)
动态绑定:后期绑定(晚绑定),在编译的时候并不能确定方法的行为,只有真正运行的时候才能知道方法具体是执行哪个类的哪个方法。(向上转型就发生了动态绑定)

向上转型和向下转型

向上转型

向上转型:创建一个子类对象,再将其赋值给父类。小范围转向大范围

父类 对象名 = new 子类();
Eg:Animal animal = new cat();

我们来谈一谈向上转型的内部原理:我在这画了一个大概的图,希望你们能看懂。
在这里插入图片描述

看上图,我们应该有了些许了解,那么我们也可以知道,对于子类而言,在堆中存储的子类对象有两部分:继承下来的和子类自己的内容。下面重点来喽!
向上转型调用的到底是父类的还是子类的呢
1.由于我们进行了向上转型,所以定义的变量只可以访问子类的继承的部分内容。
2 .由于向上转型发生了动态绑定,所以当调用子类父类同名的方法的时候,本来该调用父类的,但由于执行时会调用子类的。
3 .由于向上转型只可以访问子类的继承部分,所以根本访问不到子类特有的方法。(这也就是向上转型的一大弊端)。

这里借鉴我看过的博主的一个图片,我感觉这个图片很好,很方便理解。
在这里插入图片描述
向上转型可以用下面三种方法来应用。
1.直接赋值
2.方法传参
3.作为返回值
有这三种场景可以发生向上转型,我们来看代码吧

class Animal {
    String name;
    int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat() {
        System.out.println(name + "吃饭");
    }
}
class Cat extends Animal {
    public Cat(String name, int age) {
        super(name,age);
    }
    @Override
    public void eat() {
        System.out.println(name + "吃鱼");
    }
}
class Dog extends Animal {
    public Dog(String name, int age) {
        super(name,age);
    }
    @Override
    public void eat() {
        System.out.println(name + "吃骨头");
    }
}
public class JavaSE730 {
    //2.通过参数来向上转型,用父类来接受,可以介绍任何的子类
    public static void eatFood(Animal a){
        a.eat();
    }
    //3.当成返回值来向上转型
    public static Animal buyAnimal(String var){
        if("狗" == var){
            return new Dog("狗狗",1);
        }else if("猫" == var){
            return new Cat("猫猫", 1);
        }else{
            return null;
        }
    }
    public static void main(String[] args) {
        Animal cat = new Cat("元宝",2); // 1. 直接赋值:子类对象赋值给父类对象
        Dog dog = new Dog("小七",3);
        eatFood(cat);
        eatFood(dog);//2.将子类dog对象传过去,那边用Animal接收,也发上向上转型
    }
}

向下转型

我们上面提到了,向上转型的话,我们不能访问子类独有的内容,而我们有时又想要访问独有的内容,这就引出来了向下转型。向下转型即将父类引用对象还原为子对象。

Cat cat = new Cat("元宝",2);
Animal animal = cat;//向上转型
cat = (Cat)animal;//向下转型

向下转型并不常用,因为不安全。如果原来子类为猫,向上转型后再向下转型为猫没有问题,因为原来就为猫类;但是假设原来为狗类向下转型为猫类则就出错了,这也正是不安全的地方。狗一定是动物而动物并不一定是狗。

instanceof

如果向下转型的时候子类不对应的话,会抛出异常,在Java中我们可以通过instanceof进行处理异常。

if(animal instanceof Cat){//判断向上转型时的子类是否为cat,是进行下面操作
cat = (Cat)animal;
cat.mew();
}

抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

上面那个了解就可以,下面内容才是重要的!
1.被abstract修饰的类为抽象类,被abstract修饰的方法为抽象方法,抽象方法不用有方法体并且要有分号。

abstract class A {
    abstract void func();
}

2.抽象类也可以包含普通方法和属性,也可以有构造方法。
3.抽象类不可以进行实例化。
4.抽象类存在的意义就是被继承。
5.抽象方法不可以被private修饰,也不能被final和static修饰,因为抽象方法要保证能重写。
6.抽象类不可以被final修饰,要保证抽象类能被继承。
7.抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用 abstract 修饰。
8.抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类。

  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值