java的三大特性之一:多态

多态(polymorphism)

1、多态的形式

Java规定父类类型的变量可以接收子类类型的对象,这一点从逻辑上也是说得通的。

父类类型 变量名 = 子类对象;

父类类型:指子类继承的父类类型,或者实现的父接口类型。

所以说继承是多态的前提

//多态的引用形式

Animal a = new Cat();//Cat对象也属于其父类Animal类型。猫也是一个动物。

2、多态的表现

多态引用形式的具体表现:编译时类型与运行时类型不一致,编译时看左边的父类,运行时看右边的子类

也就是我们常说的:编译看左边,运行看右边。

public class Book {
    private String bookName;
    private String author;
    private double price;
    public Book() {

    }
    public Book(String bookName, String author, double price) {
        this.bookName = bookName;
        this.author = author;
        this.price = price;
    }

    public void say(){
        System.out.println("这是一本书");
    }

}
public class Novel extends Book{
    public Novel() {

    }
    public Novel(String bookName, String author, double price) {
        super(bookName, author, price);
    }

    @Override
    public void say() {
        System.out.println("这是一本小说");
    }
    public void author(){
        System.out.println("这本小说的作者是张三");
    }
}
public class Test {
    public static void main(String[] args) {
        Book book = new Novel();
        book.say();
    }
}

当我们想用book调用子类的author方法时出现错误

 

        我们可以看到我们在创建对象时用的父类的类型以及子类的对象,并且在编译后实际执行的是子类Novel中的say方法,也就是运行看右边。

        但当我们想用book调用子类的author方法时这就会发生错误,因为我们在编译的时候呈现的是父类的特征,而父类没有author方法,所以这就是编译看左边。

3、多态的好处

运行时,看“子类”,如果子类重写了方法,一定是执行子类重写的方法;变量引用的子类对象不同,执行的方法就不同,实现动态绑定。代码编写更灵活、功能更强大,可维护性和扩展性更好了。

提高程序的扩展性

降低类与类之间的耦合度

 

前面提到了当父类类型想调用子类方法时会发生错误,但是我们有时候又需要调用子类的方法,这时,我们就可以用到类型转换。

1、为什么要类型转换呢?

因为多态,就一定会有把子类对象赋值给父类变量的时候,这个时候,在编译期间,就会出现类型转换的现象。

但是,使用父类变量接收了子类对象之后,我们就不能调用子类拥有,而父类没有的方法了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做类型转换,使得编译通过。

向上转型:当左边的变量的类型(父类) > 右边对象/变量的类型(子类),我们就称为向上转型

此时,编译时按照左边变量的类型处理,就只能调用父类中有的变量和方法,不能调用子类特有的变量和方法了

但是,运行时,仍然是对象本身的类型,所以执行的方法是子类重写的方法体。

此时,一定是安全的,而且也是自动完成的

向下转型:当左边的变量的类型(子类)<右边对象/变量的编译时类型(父类),我们就称为向下转型

此时,编译时按照左边变量的类型处理,就可以调用子类特有的变量和方法了

但是,运行时,仍然是对象本身的类型

不是所有通过编译的向下转型都是正确的,可能会发生ClassCastException,为了安全,可以通过instanceof关键字进行判断

2、如何向上转型与向下转型

向上转型:自动完成

向下转型:(子类类型)父类变量

public class Test {
    public static void main(String[] args) {
        Book book = new Novel();
        book.say();
        ((Novel)book).author();
    }
}

3、instanceof关键字

instanceof关键字用于判断一个对象的运行时类型

为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,只要用instanceof判断返回true的,那么强转为该类型就一定是安全的,不会报ClassCastException异常。

格式:

变量/匿名对象 instanceof 数据类型

 

那么,哪些instanceof判断会返回true呢?

变量/匿名对象的编译时类型 instanceof后面数据类型是直系亲属关系才可以比较

变量/匿名对象的运行时类型<= instanceof后面数据类型,才为true

public class Type {
    public void say(Book book){
        book.say();
        if (book instanceof Novel){
            ((Novel) book).author();
        }
    }
}

 

public class Test {
    public static void main(String[] args) {
        Book book = new Novel();
        Type type = new Type();
        type.say(book);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值