Java 多态透析 详细理解
1:什么是多态
一个对象的多种状态
(老师)(员工)(儿子)
教师 a =老钟;
员工 b =老钟;
2:多态体现
父类引用变量指向了子类的对象 Father f = new Son();
父类引用也可以接受自己的子类对象
1:Father类
1:非静态成员变量x
2:静态成员变量y
3:非静态方法eat,方法体输出父类信息
4:静态方法speak();方法体输出父类信息
class Father {
int x = 1;
static int y = 2; void eat() {
System.out.println("开吃");
} static void speak() {
System.out.println("小头爸爸");
}
}
2:Son类
1:非静态成员变量x
2:静态成员变量y
3:非静态方法eat,方法体输出子类信息
4:静态方法speak();方法体输出子类信息
class Son extends Father {
int x = 3;
static int y = 4; void eat() {
System.out.println("大头儿子很能吃");
} static void speak() {
System.out.println("大头儿子。");
}
}
class Demo1 { public static void main(String[] args) { Father f = new Son(); // 父类引用指向了子类对象。
System.out.println(f.x); // 1
System.out.println(f.y); // 2
f.eat(); // 输出的是子类的。
f.speak(); // 输出的是父类 }
}
3总结:
1:当父类和子类具有相同的非静态成员变量,那么在多态下访问的是父类的成员变量
2:当父类和子类具有相同的静态成员变量,那么在多态下访问的是父类的静态成员变量
所以:父类和子类有相同的成员变量,多态下访问的是父类的成员变量。
3:当父类和子类具有相同的非静态方法(就是子类重写父类方法),多态下访问的是子类的成员方法。
4:当父类和子类具有相同的静态方法(就是子类重写父类静态方法),多态下访问的是父类的静态方法。
多态前提
1:类与类之间有关系,继承或者实现
多态弊端
1:提高扩展性,但是只能使用父类引用指向父类成员。
多态特点
非静态
1:编译时期,参考引用型变量所属的类是否有调用的方法,如果有编译通过。没有编译失败
2:运行时期,参考对象所属类中是否有调用的方法。
3:总之成员函数在多态调用时,编译看左边,运行看右边。
在多态中,成员变量的特点,无论编译和运行 参考左边(引用型变量所属的类)。
在多态中,静态成员函数特点,无论编译和运行都参考左边
多态练习
1:多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。
1:定义功能,根据输出任何图形的面积和周长。
abstract class MyShape{
public abstract double getArea();
public abstract double getLen();
}
2:定义Rect类继承MyShape
class Rect extends MyShape{
double width ;
double height;
Rect(){
}
Rect(double width ,double height){
this.width=width;
this.height=height;
}
public double getArea(){
return width*height;
}
public double getLen(){
return 2*(width+height);
}
}
3:定义Cricle类继承MyShape
class Circle extends MyShape{
double r;
public static final double PI=3.14;
Circle(){
}
Circle(double r){
this.r=r;
}
public double getLen(){
return 2*PI*r;
}
public double getArea(){
return PI*r*r;
}
}
4:定义静态方法计算任意图形的面积和周长
1:未知内容参与运算,不能确定用户传入何种图形,使用多态。
1:形参定义为 MyShape my
2:调用计算面积方法,和计算周长方法。并打印
2:使用多态特性,子类重写了父类非静态方法,会执行子类的方法。
class Demo2{
public static void main(String[] args){
System.out.println();
print(new Rect(3,4)); //MyShape m =new Rect(3,4);
print(new Circle(3));
}
//根据用户传入的图形对象,计算出该图形的面积和周长
//1:多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。
public static void print(MyShape m){
System.out.println(m.getLen());
System.out.println(m.getArea());
}
}
2:多态可以作为返回值类型。
获取任意一辆车对象
1:定义汽车类,有名字和颜色,提供有参和无参构造,有运行的行为。
class Car {
String name;
String color;
Car() {
}
Car(String name, String color) {
this.name = name;
this.color = color;
}
void run() {
System.out.println("跑跑。。。。");
}
}
2:定义Bmw类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
class Bmw extends Car {
Bmw() {
}
Bmw(String name, String color) {
super(name, color);
}
void run() {
System.out.println("宝马很拉风。。。。");
}
}
3:定义Benz类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
class Benz extends Car {
Benz() {
}
Benz(String name, String color) {
super(name, color);
}
void run() {
System.out.println("奔驰商务首选。。。。");
}
}
4:定义Bsj类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
class Bsj extends Car {
Bsj() {
}
Bsj(String name, String color) {
super(name, color);
}
void run() {
System.out.println("泡妞首选。。。。");
}
}
5:定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。
1:使用(int)Math.round(Math.random()*2); 生成0-2之间随机数。
2:使用if else 判断,指定,0,1,2 new 不同汽车 并返回。
class Demo3 {
public static void main(String[] args) {
int x = 0;
while (x < 100) {
Car c = CarFactory();
c.run();
x++;
}
} // 定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。
// 使用随机数,0.1.2 if 0 bsj 1 bmw 2 bc
public static Car CarFactory() {
int x = (int) Math.round(Math.random() * 2);
if (0 == x) {
return new Bmw("宝马x6", "红色");
} else if (1 == x) {
return new Benz("奔驰", "黑色");
} else if (2 == x) {
return new Bsj("保时捷", "棕色");
} else {
return new Benz("Smart", "红色");
}
}
}
3:抽象类和接口都可以作为多态中的父类引用类型。 多态之类型转型
1:案例定义Father类
1:定义method1和method2方法
class Father {
void method1() {
System.out.println("这是父类1");
}
void method2() {
System.out.println("这是父类2");
}
}
2:定义Son类继承Father类
1:定义method1(重写父类method1)和method2方法
class Son extends Father {
void method1() {
System.out.println("这是子类1");
}
void method3() {
System.out.println("这是子类3");
}
}
3:创建Father f=new Son();
1: f.method1() 调用的子类或者父类?
2: f.method2() 编译和运行是否通过?
3: f.method3() 编译和运行是否通过?(编译报错)
class Demo4 {
public static void main(String[] args) {
Father f = new Son();
f.method1(); // 这是子类1
f.method2(); // 这是父类2
// f.method3(); //编译报错。
// 多态弊端,只能使用父类引用指向父类成员。
// 类类型转换
Son s = (Son) f;
s.method3();
System.out.println();
}
}
4:如何在多态下,使用父类引用调用子类特有方法。
1:基本类型转换:
1:自动:小->大
2:强制:大->小
2:类类型转换
前提:继承,必须有关系
1:自动:子类转父类
2:强转:父类转子类
3:类型转换
1:Son s=(Son)f
2:s.method3();
案例:
1:定义Animal类颜色成员变量,无参构造,有参构造,run方法
class Animal {
String color;
Animal() {
}
Animal(String color) {
this.color = color;
}
void run() {
System.out.println("跑跑");
}
}
2:定义Dog类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Dog的特有方法ProtectHome
class Dog extends Animal {
Dog() {
}
Dog(String color) {
super(color);
}
void run() {
System.out.println("狗儿跑跑");
}
void protectHome() {
System.out.println("旺旺,看家");
}
}
3:定义Fish类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Fish特有方法swim
class Fish extends Animal {
Fish() {
}
Fish(String color) {
super(color);
}
void run() {
System.out.println("鱼儿水中游");
}
void swim() {
System.out.println("鱼儿游泳");
}
}
4:使用多态,Animal a=new Dog();
5:调用Dog的特有方法,ProtectHome
1:类类型转换,Dog d=(Dog)a;
2:d.protectHome
class Demo5 { public static void main(String[] args) { Animal ani = new Dog();
// ani.protectHome();
// 正常转换
Dog d = (Dog) ani;
d.protectHome(); // 多态例外
Animal an = new Animal();
// ClassCastException
// Dog d=(Dog)an // 多态例外
Animal dog = new Dog();
// ClassCastException
// Fish f = (Fish) dog; }
}
6:非多态
1:Animal a=new Animal();
2:类类型转换
Dog d=(Dog)a;
d.protectHome();
3:编译通过,运行出现异常
1:ClassCastException
7:多态例外
1:Animal a=new Dog();
2:类类型转换
1:Fish f=(Fish)a;
2:f.fish();
3:编译通过,运行异常
1:ClassCastException
4:虽然是多态,但是狗不能转为鱼,他们之间没有关系。
案例2
1:定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法
2:使用多态,方法形参,不能确定用户传入的是那种动物
3:使用instanceof 关键字,判断具体是何种动物,
4:类转换,执行该动物的特有方法。
class Animal {
String color;
Animal() {
}
Animal(String color) {
this.color = color;
}
void run() {
System.out.println("跑跑");
}
}
class Dog extends Animal {
Dog() {
}
Dog(String color) {
super(color);
}
void run() {
System.out.println("狗儿跑跑");
}
void protectHome() {
System.out.println("旺旺,看家");
}
}
class Fish extends Animal {
Fish() {
}
Fish(String color) {
super(color);
}
void run() {
System.out.println("鱼儿水中游");
}
void swim() {
System.out.println("鱼儿游泳");
}
}
class Bird extends Animal {
Bird() {
}
Bird(String color) {
super(color);
}
void run() {
System.out.println("鸟儿空中飞");
}
void fly() {
System.out.println("我是一只小小鸟。。。。");
}
}
class Demo6 {
public static void main(String[] args) {
System.out.println();
doSomething(new Dog());
doSomething(new Bird());
doSomething(new Fish());
}
// 定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法
public static void doSomething(Animal a) {
if (a instanceof Dog) {
Dog d = (Dog) a;
d.protectHome();
} else if (a instanceof Fish) {
Fish f = (Fish) a;
f.swim();
} else if (a instanceof Bird) {
Bird b = (Bird) a;
b.fly();
} else {
System.out.println("over");
}
}
}
Java 多态透析 详细理解的更多相关文章
- Java ssh 框架 hibernate 详细理解
Hibernate框架技术相信对大多数的 java 程序员并不陌生,数据表之间的关系如何通过Hibernate来建立,需要我们认真的分析数据表中数据项之间的交互: 数据库表的之间的关系有: (1)一对 ...
- Java设计模式透析之 —— 策略(Strategy)
今天你的leader兴致冲冲地找到你,希望你能够帮他一个小忙.他如今急着要去开会.要帮什么忙呢?你非常好奇. 他对你说.当前你们项目的数据库中有一张用户信息表.里面存放了非常用户的数据.如今须要完毕一 ...
- Java设计模式透析之 —— 模板方法(Template Method)
今天你还是像往常一样来上班,一如既往地開始了你的编程工作. 项目经理告诉你,今天想在server端添加一个新功能.希望写一个方法.能对Book对象进行处理.将Book对象的全部字段以XML格式进行包装 ...
- Java设计模式透析之 —— 组合(Composite)
听说你们公司最近新推出了一款电子书阅读应用,市场反应很不错,应用里还有图书商城,用户可以在其中随意选购自己喜欢的书籍.你们公司也是对此项目高度重视,加大了投入力度,决定给此应用再增加点功能. 好吧,你 ...
- Java设计模式透析之 —— 单例(Singleton)
写软件的时候经常需要用到打印日志功能,可以帮助你调试和定位问题,项目上线后还可以帮助你分析数据.但是Java原生带有的System.out.println()方法却很少在真正的项目开发中使用,甚至像f ...
- Java设计模式透析之 —— 适配器(Adapter)
转载请注明出处:http://blog.csdn.net/sinyu890807/article/details/9400141 今天一大早,你的leader就匆匆忙忙跑过来找到你:“快,快,紧急任务 ...
- Java经验杂谈(2.对Java多态的理解)
多态是面向对象的重要特性之一,我试着用最简单的方式解释Java多态: 要正确理解多态,我们需要明确如下概念:・定义类型和实际类型・重载和重写・编译和运行 其中实际类型为new关键字后面的类型. 重载发 ...
- Ruby设计模式透析之 —— 适配器(Adapter)
转载请注明出处:http://blog.csdn.net/sinyu890807/article/details/9400153 此为Java设计模式透析的拷贝版,专门为Ruby爱好者提供的,不熟悉R ...
- Ruby设计模式透析之 —— 组合(Composite)
转载请注明出处:http://blog.csdn.net/sinyu890807/article/details/9153761 此为Java设计模式透析的拷贝版,专门为Ruby爱好者提供的,不熟悉R ...
随机推荐
- zabbix监控Elasticsearch集群
本节以 zabbix 为例,介绍如何使用监控系统完成 Elasticsearch 的监控报警. github 上有好几个版本的 ESZabbix 仓库,都源自 Elastic 公司员工 unterge ...
- Sampling Distributions and Central Limit Theorem in R(转)
The Central Limit Theorem (CLT), and the concept of the sampling distribution, are critical for unde ...
- kafka 0.10.2 消息生产者(producer)
package cn.xiaojf.kafka.producer; import org.apache.kafka.clients.producer.*; import org.apache.kafk ...
- js的event事件
一 . 焦点:使浏览器能够区分区分用户输入的对象,当一个元素有焦点的时候,那么他就可以接收用户的输入. 我们可以通过一些方式给元素设置焦点 1.点击 2.tab 3.js 不是所有元素都能够接受 ...
- Scrapy中使用Django的Model访问数据库
Scrapy中使用Django的Model进行数据库访问 当已存在Django项目的时候,直接引入Django的Model来使用比较简单 # 使用以下语句添加Django项目的目录到path impo ...
- Asp.Net Core-----简介与安装
Asp.Net Core简介 ASP.NET Core 是一个全新的开源.跨平台框架,可以用它来构建基于网络连接的现代云应用程序,比如:Web 应用,IoT(Internet Of Things,物联 ...
- DOUAudioStreamer 中kqueue的应用
DOUAudioStreamer是一个基于Core Audio的流式音频播放器,其中的DOUAudioEventLoop通过kqueue来控制音频的各种状态. kqueue简介(详情请看官方manua ...
- MACOS关闭指定端口
因为用IDEA写项目的时候,有的时候结束Jetty导致端口没有释放,所以会出现占用的情况. MacOS结束端口占用进程的命令,和Linux的一样.先执行如下命令: lsof -i:8080 会有类似下 ...
- Thinkphp 3.0-3.1版代码执行漏洞
近日360库带计划中播报的ThinkPHP扩展类库的漏洞已经查明原因:系官方扩展模式中的Lite精简模式中存在可能的漏洞(原先核心更新安全的时候 并没有更新模式扩展部分,现已更新).对于使用标准模式或 ...
- 软件测试基础(软件测试分类和工具组)firebug、firepath的安装
白盒测试:需要了解内部结构和代码 黑盒测试:不关心内部结构和代码 灰盒测试:介于白盒黑盒之间 静态测试:测试时不执行被测试软件 动态测试:测试时执行被测试软件 单元测试:测试软件的单元模块 集成测试: ...