专业的JAVA编程教程与资源

网站首页 > java教程 正文

初识Java—(十八)多态(java中多态是什么)

temp10 2024-09-27 22:54:36 java教程 9 ℃ 0 评论

某一个事物,在不同时刻表现出来的不同状态,称为多态。比如:水,水有多种表现形式,液体,固体,气体。

而在Java中,引用变量有两个类型,一个是编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现多态。所谓的多态就是同样一个东西表现出多种不同的方式。

初识Java—(十八)多态(java中多态是什么)

5.7.1 多态性

Java中的多态性也是由Java面向对象中继承特征导致的。因为子类是一种特殊的父类,因此Java允许把一个子类对象直接赋值给父类引用变量,无须任何类型转换。或者称为向上转型,向上转型由系统自动完成。如果子类重写了父类的方法,那么使用父类引用变量指向不同的子类时,调用方法相同,但表现形式有所不同,这种现象就成为多态。

而要体现出多态性来,还需要一个工作就是要做方法的重写操作,这样才能体现出多态性,可以不写,但是不写就没任何意义了。

举例1:

package com.langsin.test;
public class BmwCar extends Car {
public String name = “Bmw”;
public void run() {
System.out.println("我是宝马车。。。。");
}
}
=======================================================
package com.langsin.test;
public class BenzCar extends Car {
public String name= “Benz”;
public void run() {
System.out.println("我是奔驰车。。。。");
}
}
========================================================
package com.langsin.test;
public class Car {
public String name = “Car”;
public void run(){
System.out.println("我是所有车的父类......");
}
public static void main(String args[]){
//编译时类型与运行时类型完全一致,所以不存在多态
Car car = new Car();
car.run();
//编译时类型与运行时类型不一致,所以存在多态
Car car1 = new BmwCar();
car1.run();
//编译时类型与运行时类型不一致,所以存在多态
Car car2 = new BenzCar();
car2.run();
}
}

看了多态的表现形式,那我们现在来思考实际操作中我们经常会碰到的问题。如果父类,子类中出现了同名的成员变量。那么在调用输出时调用的是哪一个?如果父类引用对象调用了本身中没有但子类中存在的成员变量时又会怎么样?看下面代码的结果。

例如:

class Car{
public String price = “100000”;
public void print(){
System.out.println(“我就是辆车!”);
}
}

class BmwCar extends Car{
public String price = “450000”;
public String price1 = “530000”;
public void print(){
System.out.println(“我是宝马车!”);
}
}

class TestDemo{
public static void main(String[] args){
Car car = new BmwCar();
System.out.println(car.price);//
System.out.println(car.price1);//
car.print();//
}
}

通过上面的代码我们就看出了,在多态中,成员访问的特点是什么样的。

成员变量:编译看左边,运行看左边。

成员方法:编译看左边,运行看右边。

静态方法:编译看左边,运行看左边。静态和类相关,算不上重写,所以访问还是左边。

这里又说了,如果子类中有父类中没有的方法。多态的情况下,父类的引用对象,调用子类里的方法。会出现什么样的结果呢?这个放在多态的弊端中讲。

5.7.1.1多态的利与弊:

多态的好处:

(1) 提高了代码的维护性(继承保证)

(2) 提高了代码的扩展性

扩展性我们通过代码把这个扩展性来看一下。

public class Car {
public void print(){}
public void price(){}
}

public class BmwCar extends Car {
@Override
public void print() {
// TODO Auto-generated method stub
System.out.println("Bmw");
}

public void price() {
// TODO Auto-generated method stub
System.out.println("300000");
}
}

public class BenzCar {
public void print() {
// TODO Auto-generated method stub
System.out.println("BenzCar");
}

public void price(){
System.out.println("300000");
}
}

public class PolymorphismDemo1 {
public static void main(String[] args) {

/*

* (1)我喜欢宝马车,我就要创建一个宝马的对象,我还喜欢,再买一辆,我有钱,如果我买了多辆呢?一直创建对象吗?

* 我们调用的都是同一个方法。就是对象不同而已。怎么解决?

* 解决:我们用方法改进,把宝马的方法写在同一个方法中。想一个,新写的方法写在哪?

* 写在一个新的类里边,测试类只做测试用。

* (2)如果我也喜欢BenzCar呢? 同样。把BenzCar的方法写在一个方法里。

* (3)我喜欢保时捷呢?怎么操作?

* 1.定义一个保时捷类2.继承自车类3.重写方法4.并在工具类中添加方法的调用。

* 前三步必须写。没问题。但是工具类每次都要改,都要新添加。怎么解决?

* 解决:我们用的都是车,那我们在工具类中的方法里用车来接收一下可以不?

改一下工具类看一下。

*/

// public static void buyBmw(BmwCar c) {
// c.print();
// c.price();
// }
//
// public static void buyBenz(BenzCar z) {
// z.print();
// z.price();
// }

}

}

public class CarDemo {
// public static void buyBmw(BmwCar c) {
// c.print();
// c.price();
// }
//
// public static void buyBenz(BenzCar z) {
// z.print();
// z.price();
// }
public static void useCar(Car c){
c.print();
c.price();
}
}


多态的弊端:

不能使用子类的特有功能,只能使用父类中定义过的功能。如果父类的引用调用了子类中独有方法,会造成一种什么结果呢?

例如:

class Car{
public String price = “100000”;
public void print(){
System.out.println(“我就是辆车!”);
}
}

class BmwCar extends Car{
public String price = “450000”;
public void print(){
System.out.println(“我是宝马车!”);
}
public void price(){
}
}

class TestDemo{
public static void main(String[] args){
Car car = new BmwCar();
System.out.println(car.price);
car.price();
car.print();
}
}

那我就想用怎么办。看下面。

5.7.2 引用变量的强制类型转换

上面的问题现在就可以解决了。我们想用子类中的方法,可以直接创建一个子类的对象,然后通过子类对象引用就可以了,但这样会重新分配内存空间,占用内存。

编写Java程序时,引用变量只能调用它编译时类型的方法,而不能调用它运行时类型中独有的方法,即使它实际引用的对象确实包含该方法,也无法引用到。如果需要让这个引用变量调用它运行时类型的方法,则必须把它强制转换成运行时类型,强制类型转换需要借助于类型转换运算符。

举例1:

package com.langsin.test;
public class BmwCar extends Car {
public void run() {
System.out.println("我是宝马车。。。。");
}
public void description(){
System.out.println("高端、大气、上档次");
}
}

package com.langsin.test;
public class Car {
public void run(){
System.out.println("我是所有车的父类......");
}
public static void main(String args[]){
Car car = new BmwCar(); //这里可以叫向上转型
car.run();
Bmw b = (Bmw)car;
b.description(); //进行强制转换后调用子类对象中的方法。向下转型
}
}

强制类型转换不是万能的,当进行强制类型转换时需要注意:

1、 基本类型之间的转换只能在数值类型之间进行,数值类型包括整数型、字符型和浮点型。但数值类型和布尔类型之间不能进行类型转换。

2、 引用类型之间的转换只能在具有继承关系的两个类之间进行,如果两个没有任何继承关系的类型,则无法进行类型转换。如果将一个父类类型转换成子类类型,那么这个父类类型指向的实例必须是子类类型的实例才行,否则在运行时会引发类型转换异常(ClassCastException)。


举例1:

package com.langsin.test;
public class Test {
public static void main(String[] args) {
double d = 13.4;
long li = (long)d;
int a = 4;
boolean b = (boolean)a;
Object obj = "Hello World";
String str = (String)obj;
obj = new Integer(5);
str = (String)obj;
}
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表