当前位置: 首页 > news >正文

【JavaSE】多态(多态实现的条件 重写 向上转移和向下转型 向上转型 向下转型 多态的优缺点 避免在构造方法种调用重写的方法)

文章目录

  • 多态
    • 多态实现的条件
    • 重写
    • 向上转移和向下转型
      • 向上转型
      • 向下转型
    • 多态的优缺点
    • 避免在构造方法种调用重写的方法


多态

一种事物,多种形态。
多态的概念:去完成某个行为,当不同对象去完成时会产生出不同的状态。

多态实现的条件

1.必须再继承体系下。
2.子类必须要对父类中的方法进行重写。
3.通过父类的引用调用重写的方法。

在这里插入图片描述

当我们发生向上转型之后,此时通过父类引用只能访问父类自己的成员,不能访问到子类特有的成员。

重写

重写需要满足三个条件:

  1. 方法名称相同。
  2. 参数列表相同。
  3. 返回值相同。
class Animal{public String name;public int age;public void eat(){System.out.println(name+" 正在吃饭!");}
}
class Dog extends Animal{public void wangwang(){System.out.println(name+" 正在汪汪叫!");}@Overridepublic void eat(){System.out.println(name+" 正在吃狗粮!");}
}

在这里插入图片描述
编译器可以生成:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

class Animal{public String name;public int age;public void eat(){System.out.println(name+" 正在吃饭!");}
}
class Dog extends Animal{public void wangwang(){System.out.println(name+" 正在汪汪叫!");}@Overridepublic void eat(){System.out.println(name+" 正在吃狗粮!");}
}
class Bird extends Animal{public String wing;//翅膀public void fly(){System.out.println(name+" 正在飞!");}@Overridepublic void eat(){System.out.println(name+" 正在吃鸟粮!");}
}
public static void main(String[] args) {Animal animal1 = new Dog();animal1.name = "小黄";animal1.eat();System.out.println("=================");Animal animal2 = new Bird();animal2.name = "圆圆";animal2.eat();
}

在这里插入图片描述
静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载。
动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。

在这里插入图片描述

重写需要注意:

  1. private修饰的方法不能被重写。
  2. static修饰的方法不能被重写。
  3. 子类的访问修饰限定权限要大于等于父类的权限。 private < 默认 < protected < public
  4. 被final修饰的方法不能被重写,此时这个方法被称作密封方法。
    在这里插入图片描述

向上转移和向下转型

向上转型

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

  1. 直接赋值
class Animal{public String name;public int age;public void eat(){System.out.println(name+" 正在吃饭!");}
}
class Dog extends Animal{public void wangwang(){System.out.println(name+" 正在汪汪叫!");}
}
public class Test2 {public static void main1(String[] args) {Dog dog = new Dog();dog.name = "小黄";dog.eat();dog.wangwang();Animal animal = dog;}
}
  1. 方法传参
class Animal{public String name;public int age;public void eat(){System.out.println(name+" 正在吃饭!");}
}
class Dog extends Animal{public void wangwang(){System.out.println(name+" 正在汪汪叫!");}
}
public class Test2 {public static void func(Animal animal){}public static void main(String[] args) {Dog dog = new Dog();func(dog);}
}

3.方法返回值

class Animal{public String name;public int age;public void eat(){System.out.println(name+" 正在吃饭!");}
}
class Dog extends Animal{public void wangwang(){System.out.println(name+" 正在汪汪叫!");}
}
public class Test2 {public static Animal func2(){return new Dog();}public static void main(String[] args) {func2();}
}

优点:让代码实现更简单灵活。
缺陷:不能调用到子类特有的方法。

向下转型

class Animal{public String name;public int age;public void eat(){System.out.println(name+" 正在吃饭!");}
}
class Dog extends Animal{public void wangwang(){System.out.println(name+" 正在汪汪叫!");}
}
public class Test2 {public static void main(String[] args) {Animal animal1 = new Dog();//向下转型Dog dog = (Dog)animal1;dog.name = "小黄";dog.wangwang();}
}

向下转型非常不安全,比如:
在这里插入图片描述

解决方法:Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。

if(animal1 instanceof Dog){//向下转型Dog dog = (Dog)animal1;dog.name = "小黄";dog.wangwang();
}

可以理解为判断animal1这个引用,是不是引用Dog对象。

多态的优缺点

class Shap{public  void draw(){System.out.println("画图形!");}
}
class Rect extends Shap{@Overridepublic void draw() {System.out.println("画矩形!");}
}
class Cycle extends Shap{@Overridepublic void draw() {System.out.println("画圆!");}
}
class Flower extends Shap{@Overridepublic void draw() {System.out.println("画一朵花❀!");}
}
public class Test3 {public static void drawMap(Shap shap){shap.draw();}public static void main(String[] args) {Rect rect = new Rect();Cycle cycle = new Cycle();drawMap(rect);drawMap(cycle);drawMap(new Flower());}
}

在这里插入图片描述

class Shap{public  void draw(){System.out.println("画图形!");}
}
class Rect extends Shap{@Overridepublic void draw() {System.out.println("画矩形!");}
}
class Cycle extends Shap{@Overridepublic void draw() {System.out.println("画圆!");}
}
class Flower extends Shap{@Overridepublic void draw() {System.out.println("画一朵花❀!");}
}
public class Test3 {public static void drawMap2(){Rect rect = new Rect();Cycle cycle = new Cycle();Flower flower = new Flower();//c r c r fString[] shapes = {"cycle", "rect", "cycle", "rect", "flower"};for (String shape : shapes) {if (shape.equals("cycle")) {cycle.draw();} else if (shape.equals("rect")) {rect.draw();} else if (shape.equals("flower")) {flower.draw();}}}public static void main(String[] args) {drawMap2();}
}

在这里插入图片描述

多态实现:

public static void drawMap3(){Rect rect = new Rect();Cycle cycle = new Cycle();Flower flower = new Flower();Shap [] shaps = {cycle,rect,cycle,rect,flower};for(Shap shap:shaps){shap.draw();}
}

多态好处:

  1. 能够降低代码的 “圈复杂度”, 避免使用大量的 if - else。
  2. 可扩展能力更强如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低。

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

  1. 属性没有多态性:当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性。
  2. 构造方法没有多态性。

避免在构造方法种调用重写的方法

下面我们看一段有坑的代码:

class B {public B() {
// do nothingfunc();}public void func() {System.out.println("B.func()");}
}
class D extends B {private int num = 1;@Overridepublic void func() {System.out.println("D.func() " + num);}
}
public class Test4 {public static void main(String[] args) {D d = new D();}
}

当在父类的构造方法当中去调用父类和子类重写的方法的时候,此时会调用子类的。
num为0是因为父类此时还没有走完,就来到了打印阶段。

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

http://www.lryc.cn/news/67989.html

相关文章:

  • MySQL学习---13、存储过程与存储函数
  • Mysql日志管理、备份与恢复
  • STM32单片机声控语音识别RGB彩灯多种模式亮度可调WS2812彩灯
  • 高校9大学术工具推荐,一定要用起来哦!
  • 记一次压力测试
  • 一个文明是否有竞争力,在很大程度上取决于信息传递的效率。
  • 测试4年,跳槽一次涨8k,我跳了3次···
  • Redis 入门教程(简单全面版)
  • java并发-AQS
  • openAI图像生成开发文档
  • Python综合案例—利用tkinter实现计算器的程序
  • canvas学习笔记
  • Navicat Premium 15安装注教程
  • yolo v8
  • 2022IDEA的下载、安装、配置与使用
  • 实验十 超市订单管理系统综合实验
  • 微服架构基础设施环境平台搭建 -(二)Docker私有仓库Harbor服务搭建
  • springboot+freemarker+restful
  • 基于Kubernetes集群构建大中型企业CICD应用平台(1)-- devOps
  • 什么是模型鲁棒性和泛化能力
  • AI翻译工具分享
  • 选男友最好的方式就是爬山
  • C++面经:初始化全局变量和未初始化全局变量有什么区别
  • vue-2 指令:
  • 非常提效的7款原型工具推荐
  • 最新Kafka和RabbitMQ消息队列经典面试题汇总(含答案)
  • 软件测试行业对新人友好吗?
  • Python requests 模块
  • IOC理论推导
  • 我的一些感悟