首页 > 编程语言 >Java中的多态

Java中的多态

时间:2024-04-08 12:34:07浏览次数:22  
标签:Java 重写 多态 子类 父类 方法 public

1.1 多态的概念

多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。同一件事情,发生在不同对象身上,就会产生不同的结果。

1.2 多态实现条件

在java中要实现多态,必须要满足如下几个条件,缺一不可:

1. 必须在继承体系下

2. 子类必须要对父类中方法进行重写

3. 通过父类的引用调用重写的方法

多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。

1.3重写

重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

1.3.1 方法重写的规则

1.子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致

2.被重写的方法返回值类型可以不同,但是必须是具有父子关系的

3.访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为protected

4.父类被static、private修饰的方法、构造方法都不能被重写。

5.重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写.

1.3.2 重载和重写的区别

1.参数列表:重载必须改变参数列表,重写一定不能改变参数列表

2.返回类型:重载可以修改返回类型,重写一定不能修改(除非构成父子关系)

3.访问限定符:重载可以修改返回类型,重写一定不能做更严格的限制(可以降低限制)

即:方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现

1.4 重写的设计原则

对于已经投入使用的类,尽量不要进行修改。最好的方式是:重新定义一个新的类,来重复利用其中共性的内容,并且添加或者改动新的内容。

2. 静态绑定和动态绑定

静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用哪个方法。典型代表函数重载。

动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用哪个类的方法。

3. 向上转移和向下转型

3.1 向上转型

向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。

语法格式:父类类型 对象名 = new 子类类型()

Animal animal = new Cat("小白",2);

animal是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换。

使用场景

1. 直接赋值

2. 方法传参

3. 方法返回

public class TestAnimal {
// 2. 方法传参:形参为父类型引用,可以接收任意子类的对象
public static void eatFood(Animal a){
a.eat();
}
// 3. 作返回值:返回任意子类对象
public static Animal buyAnimal(String var){
if("狗".equals(var) ){
return new Dog("狗",1);
}else if("猫" .equals(var)){
return new Cat("猫", 1);
}else{
return null;
}
}
public static void main(String[] args) {
Animal cat = new Cat("元宝",2); // 1. 直接赋值:子类对象赋值给父类对象
Dog dog = new Dog("小七", 1);
eatFood(cat);
eatFood(dog);
Animal animal = buyAnimal("狗");
animal.eat();
animal = buyAnimal("猫");
animal.eat();
}
}

向上转型的优点:让代码实现更简单灵活。

向上转型的缺陷:不能调用到子类特有的方法。

3.2 向下转型

将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可,即向下转换。

向下转型不安全,一般用的少。Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。

4. 多态的优缺点

4.1 使用多态的优点和缺点

1. 能够降低代码的 "圈复杂度", 避免使用大量的 if - else.如果使用使用多态, 则不必写这么多的 if - else 分支语句, 代码更简单.

2. 可扩展能力更强

如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低.

class Triangle extends Shape {
@Override
public void draw() {
System.out.println("△");
}
}

对于类的调用者来说(drawShapes方法), 只要创建一个新类的实例就可以了, 改动成本很低.

而对于不用多态的情况, 就要把 drawShapes 中的 if - else 进行一定的修改, 改动成本更高.

多态缺陷:代码的运行效率降低

5. 避免在构造方法中调用重写的方法

我们创建两个类, B是父类, D是子类. D中重写func方法. 并且在B的构造方法中调用 func

class B {
public B() {
// do nothing
func();
}
public void func() {
System.out.println("B.func()");
}
}
class D extends B {
private int num = 1;
@Override
public void func() {
System.out.println("D.func() " + num);
}
}
public class Test {
public static void main(String[] args) {
D d = new D();
}
}
// 执行结果
//D.func() 0

1.构造 D 对象的同时, 会调用 B 的构造方法.

2.B 的构造方法中调用了 func 方法, 此时会触发动态绑定, 会调用到 D 中的 func

3.此时 D 对象自身还没有构造, 此时 num 处在未初始化的状态, 值为 0. 如果具备多态性,num的值应该是1.

4.所以在构造函数内,尽量避免使用实例方法,除了final和private方法。

结论: "用尽量简单的方式使对象进入可工作状态", 尽量不要在构造器中调用方法(如果这个方法被子类重写, 就会触发动态绑定, 但是此时子类对象还没构造完成), 可能会出现一些隐藏的但是又极难发现的问题.

标签:Java,重写,多态,子类,父类,方法,public
From: https://blog.csdn.net/m0_74304844/article/details/137480808

相关文章

  • 前端学习<四>JavaScript基础——11-流程控制语句:选择结构(if和switch)
    代码块用{}包围起来的代码,就是代码块。在ES5语法中,代码块,只具有分组的作用,没有其他的用途。代码块中的内容,在外部是完全可见的。举例: {   vara=2;   alert('qianguyihao');   console.log('千古壹号'); } ​ console.log('a='+a);打印结......
  • 前端学习<四>JavaScript基础——10-运算符
    我们在前面讲过变量,本文讲一下运算符和表达式。运算符的定义和分类运算符的定义运算符:也叫操作符,是一种符号。通过运算符可以对一个或多个值进行运算,并获取运算结果。表达式:数字、运算符、变量的组合(组成的式子)。表达式最终都会有一个运算结果,我们将这个结果称为表达式的......
  • JAVA语言学习-Day5
    集合Java中的集合是工具类,可以存储任意数量的具有共同属性的对象应用场景无法预测存储数据的数据同时存储具有一对一关系的数据需要进行数据的增删数据重复问题体系结构Collection:List、Queue、SetMap:HashMapList有序且可重复,ArrayList、LinkedList......
  • Java类全路径冲突解决方法
    1.问题今天在开发中遇到这样一个问题,A同事在导入了我们的实验SDK后,发现实验无法正常获取,查看日志发现了NoClassDefFoundError异常,无法加载的的类中逻辑比较简单,只依赖了另外一个SDK包2.NoClassDefFoundError分析和解决一般情况下,碰到NoClassDefFoundError错误,首先我们会想到......
  • Java零基础入门-String
    一、概述        近期有个小伙伴在看我的文章,说我在讲完基本类型,只是顺带提了一嘴String,然后说他的老师在课上对这String讲了足足一节课,好家伙,我觉得啊,这勾起了我的回忆,当初我看String的源码及知识点时,也是看了很久,这怪我,疏忽大意了啊。既然被这位小伙伴吐槽,那我就为......
  • Java零基础入门-多态
    一、概述        我之前上几期是教学了java类、及面向对象编程的三大基本特性,封装继承和多态。前一期,我是把继承大致讲了一遍,不知道你们对它有没有理解,何为继承,继承有啥好处,可以多继承嘛?等这类问题,我在上一期内容都有讲解,如果你们答不出来,没关系,你们可以再回去瞅瞅。......
  • java8 Lambda 异常处理
    异常接口publicclassTry{ publicstatic<T>Consumer<?superT>of(UncheckedConsumer<T>action){ Objects.requireNonNull(action); returnt->{ try{ action.accept(t); }catch(Exceptione){ thrownewRuntimeExcepti......
  • JavaScript性能优化
    JavaScript性能优化JavaScript是前端开发中最常用的脚本语言之一,优化它的性能可以有效地提升页面响应速度和流畅度。下面介绍一些常见的JavaScript性能优化方法: 1.函数节流函数节流是指在一定时间内只执行一次函数,比如鼠标滚动事件,如果没有限制,那么每次鼠标滚动都会触发大量......
  • Java 方法真人游戏网站app
    在前面几个章节中我们经常使用到 System.out.println(),那么它是什么呢?println()是一个方法。System是系统类。out是标准输出对象。这句话的用法是调用系统类System中的标准输出对象out中的方法println()。那么什么是方法呢?Java方法是语句的集合,它们在......
  • Java中null和空的区别
    null是没有地址,会报空指针异常即报错。""是有地址但是里面的内容是空的。问题一:null和""的区别......