Java基础00-多态19
1. 多态
1.1 多态概述

代码示例:
动物类:
public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}
猫类:
多态的前提有继承/实现关系,所以猫类要继承动物类。
public class Cats extends Animal {
}
多态的前提要有方法重写,所以要重写父类的eat()方法。
public class Cats extends Animal {
@Override
public void eat(){
System.out.println("猫吃鱼");
}
}
实现类:
要有父类引用指向子类对象
public class AnimalDemo {
public static void main(String[] args) {
//有父类引用指向子类对象
Animal a = new Cats();
}
}
这样就满足了多态的前提,这样的现象就称之为多态。
1.2 多态中成员和成员变量访问特点
- 访问成员变量的特点:
直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
- 访问成员方法的特点:
看new的是谁,就优先用谁,没有则向上找。

代码示例:
动物类:
public class Animal {
int age = 40;
public void eat(){
System.out.println("动物吃东西");
}
}
猫类:
继承了动物类,并重写的父类的eat()方法
public class Cats extends Animal {
public int age = 20;
public int weight = 10;
@Override
public void eat(){
System.out.println("猫吃鱼");
}
public void playGame(){
System.out.println("猫捉迷藏");
}
}
测试类:
a.age调用可以使用,但是a.weight调用不可以使用,
因为,虽热内存中指向的是子类new Cat(),但是外界看到的是Animal a,通过多态的方式在访问成员变量的时候它的编译要看左边(父类),要看左边(父类)中有没有,有就可以调用,没有就不可以调用。

接下来运行测试类:
通过多态的形式,去访问成员变量,其实是访问左边(父类)中的,所以,通过多态的形式,访问成员变量,它的编译看右边,运行也看右边。

接下来调用成员方法:
调用a.eat()方法成功,a.playGame()失败,
可见调用成员方法和变量是一样的,编译也要看左边(父类),右边有可以通过,没有就不可以。

运行测试类:
运行的是重写后的方法,由此可见
通过多态的方式,调用成员变方法看的是右边(子类),运行看右边

1.3 多态的好处和弊端

代码示例:
类目录:

动物类:

猫类:
猫类继承了动物类并重写了它的eat()方法。

动物操作类:
它的成员方法的形成类型是Cat。

测试类:

运行测试类并调用操作类的方法:

运行:
ao.useAnimal,解析:
调用ao(操作类)中的useAnimal成员方法,
useAnimal方法的形参类型是Cat(猫类),
所以将main方法中的Cat c(指向的就是new Cat())(猫类)放入形参中,此时的形参相当于:Cat c = new Cat();

c.eat()方法调用猫类的eat方法,
输出“猫吃鱼”。

再加一个狗类型:
和上面的一样,先创建一个狗类,再在操作类中添加一个新的useAnimal方法这次的形参类型是狗类,调用的是狗类的eat方法。

运行:

这样的方法明显比较麻烦,如果要创建多个动物就要重复上面的每一个步骤,
所以我们运用多态。
修改操作类:
将useAnimal方法中的形参变为Animal(动物类),
因为不管猫还是狗,它们都继承Animal(动物类),
所以我们完全可以将Animal(动物类)作为形参。

接着运行测试类:

运行结果:

运行结果和以前一样,解析:
以Cat(猫)为例,
ao.useAnimal,
调用ao(AnimalOperator)的useAnimal方法,
useAnimal方法的形参类型是Animal(动物类),Cat(猫)类的父类也是Animal(动物类),
所以完全可以将Cat c(指向new Cat())赋值给Animal(动物类),这样就变成了,Animal a = new Cat();

这样就形成了多态,多态调用成员方法时,编译看左边,运行看右边,
所以我们就是输出“猫吃鱼”
这样利用多态就可以省去多个步骤,创建一个useAnimal方法即可。
但是这样不可以调用子类的特有方法,因为编译看左边(父类)。
1.4 多态中的转型

代码示例:
动物类:

猫类:

测试类:

向上转型:
父类引用指向子类对象,子类对象赋值给父类引用

运行:

但是通过向上转型的方法,访问不了子类特有的方法。

所以要用到向下转型
父类引用a转为子类对象Cat,赋值给Cat

运行:

1.5 多态转型内存图解

从main方法开始执行,加载到栈内存

Animal a加载到栈内存

在堆内存中new一片空间(001),Cat继承了Animal,所以将地址001赋值给Animal a。
这也叫向上转型

多态中执行方法,编译看左边,执行看右边,将Cat类加载到栈内存中,调用eat方法,输出“猫吃鱼”。
调用完毕后从栈内存消失

执行Cat c = (Cat) a;,将Cat c加载到栈内存中

a指向的是堆内存中的001,而001就是Cat,所以001完全可以赋值给Cat
这就是向下转型

c指向地址001(Cat),所以可以调用Cat中的方法。

执行a = new Dog();,先在堆内存中new一片空间002,Dog也继承了Animal,所以也可以赋值给a,这时a的地址值变了002。

执行a.eat():,调用方法执行看右边,进入Dog类执行eat()方法,输出“狗吃骨头”。
方法执行结束从栈内存消失。

Cat cc = (Cat) a;,将Cat cc加载到栈内存,(Cat) a,a的地址值是002,002对应的是Dog方法。

虽然猫和狗都继承自Animal但是两者是没有任何关系的,所以他们相互之间是不能进行转换的。

所以这个地方是错误的,如果强制执行就会报错,类型转换异常。

1.6 使用多态的好处

1.7 案例

public class Animal {
private String name;
private int age;
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
public Animal(){
System.out.println("无参构造方法");
}
public Animal(String name, int age){
System.out.println("有参构造方法");
}
public abstract void eat();
}
public class Cat extends Animal {
public Cat(){
super();
System.out.println("猫子类无参构造方法");
}
public Cat(String name, int age){
super(name, age);
System.out.println("猫子类有参构造方法");
}
public void eat(){
System.out.println("猫吃鱼");
}
}
public class Dog extends Animal {
public Dog(){
System.out.println("狗子类无参构造方法");
}
public Dog(String name, int age){
System.out.println("狗子类有参构造方法");
}
public void eat(){
System.out.println("狗吃骨头");
}
}
public class AnimalDemo {
public static void main(String[] args) {
Animal a = new Cat();
a.eat();//猫吃鱼
Animal b = new Dog();
b.eat();//狗吃骨头
}
}
Java基础00-多态19的更多相关文章
- Java基础十一--多态
Java基础十一--多态 一.多态定义 简单说:就是一个对象对应着不同类型. 多态在代码中的体现: 父类或者接口的引用指向其子类的对象. /* 对象的多态性. class 动物 {} class 猫 ...
- Java基础之多态和泛型浅析
Java基础之多态和泛型浅析 一.前言: 楼主看了许多资料后,算是对多态和泛型有了一些浅显的理解,这里做一简单总结 二.什么是多态? 多态(Polymorphism)按字面的意思就是“多种状态”.在面 ...
- Java基础(00)
Java发展史 Java之父:詹姆斯.高斯林(James Gosling). SUN(Stanford University Network 斯坦福大学网络公司)产物. 1995年5月23日,java ...
- 【Java基础】多态
首先先来个总结: 什么是多态 面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. 多态的定义:指允许不同类的对象对同一消 ...
- java基础之 多态
在面向对象编程(Object-Oriented Programming, OOP)中,多态机制无疑是其最具特色的功能,甚至可以说,不运用多态的编程不能称之为OOP.这也是为什么有人说,使用面向对象语言 ...
- 黑马程序员——JAVA基础之多态与Object
------- android培训.java培训.期待与您交流! ---------- 多态 : 多态定义: 某一类事物的多种存在形态. 多态的体现: 父类的引用指向了自己的子类对象. ...
- Java基础:多态(重载和重写)
转载请注明出处:jiq•钦's technical Blog (1)域与静态方法 记住"仅仅有普通方法的调用是多态的". 而域和静态方法不是:对于域的訪问.在编译期间就已经进行解析 ...
- 【Java基础】【19异常&IO(File类)】
19.01_异常(异常的概述和分类) A:异常的概述 异常就是Java程序在运行过程中出现的错误. B:异常的分类 通过API查看Throwable Error 服务器宕机,数据库崩溃等 Except ...
- java基础14 多态(及关键字:instanceof)
面向对象的三大特征: 1.封装 (将一类属性封装起来,并提供set()和get()方法给其他对象设置和获取值.或者是将一个运算方法封装起来,其他对象需要此种做运算时,给此对象调用) 2.继承 ...
- java基础(多态)_03
一.多态 1.概念:一个对象的多种形态 2.前提: a:必须有继承 b:必须有重写(只有重写才会有意义,没重写语法没错) 3.体现形式: 父类类型 变量名 = new 子类类型(): 4.注意事项: ...
随机推荐
- THINKPHP_(8)_修改TP源码,支持基于多层关联的任一字段进行排序
之前博文 前述博文THINKPHP_(1)_修改TP源码,支持对中文字符串按拼音进行排序,其解决的主要问题是,对于查询出的think\collection数据,按指定字段对数据进行排序,从而在页面上进 ...
- 5G通讯与芯片
5G通讯与芯片 美国商务部可能接近达成一项新的规则,允许美国公司与华为重启谈判,在共同制定下一代通信技术5G标准方面进行合作. 华为美国首席安全官安迪·珀迪(Andy Purdy)向第一财经记者独家回 ...
- nvGRAPH API参考分析(一)
nvGRAPH API参考分析(一) 本文通过描述nvGRAPH库函数的输入/输出参数,数据类型和错误代码来指定其行为. 1. 返回值nvgraphStatus_t 除以下内容外,所有nvGRA ...
- Python字符与字节新编
字符 字符是一个信息单位,简单来讲就是一个字母.数字.标点符号.汉字等. 字符的最佳定义是Unicode字符: 它是一个全球化的标准,能表示世界上所有语言的字符.Unicode字符的标识(码位)是以4 ...
- MySQL必知必会笔记-Mysql基本操作
Mysql基本操作 mysql的基本操作包括增.删.改.查,本书中前三章简单的介绍MySQL为何物,查是mysql中非常重要的功能,4-6章展示了mysql的查(查询--select)的简单实现,my ...
- laya fgui 超简单的UI框架
FairyGUI 超简单的UI框架 Laya使用fgui的超简单UI框架 使用场景:用于使用fgui进行layaUI开发的程序人员 整个框架分为3个模块,共有4个类: FGUIManager :FGU ...
- 搞清楚Spring事件机制后:Spring的源码看起来简单多了
本文主讲Spring的事件机制,意图说清楚: 什么是观察者模式? 自己实现事件驱动编程,对标Spring的事件机制 彻底搞懂Spring中的事件机制,从而让大家 本文内容较长,代码干货较多,建议收藏后 ...
- 08-ADMM算法
08-ADMM算法 目录 一.ADMM 算法动机 二.对偶问题 三.对偶上升法 四.对偶分割 五.乘子法(增广拉格朗日函数) 5.1 步长为 $\rho$ 的好处 六.ADMM算法 6.1 ADMM ...
- 基于ABP落地领域驱动设计-03.仓储和规约最佳实践和原则
目录 系列文章 仓储 仓储的通用原则 仓储中不包含领域逻辑 规约 在实体中使用规约 在仓储中使用规约 组合规约 学习帮助 围绕DDD和ABP Framework两个核心技术,后面还会陆续发布核心构件实 ...
- Spring Boot开发RESTful接⼝服务及单元测试
Spring Boot开发RESTful接⼝服务及单元测试 常用注解解释说明: @Controller :修饰class,⽤来创建处理http请求的对象 @RestController :Spring ...