Java 多态的详解

1.什么是多态?

一个对象的多种状态

比如:

教师 a =老钟;

员工 b= 老钟;

2.多态体现

(1)Father类

非静态成员变量x

静态成员变量y

非静态方法eat,方法体输出父类信息

静态方法speak();方法体输出父类信息

(2):Son类

非静态成员变量x

静态成员变量y

非静态方法eat,方法体输出子类信息

静态方法speak();方法体输出子类信息

class Father {
	int x = 1;
	static int y = 2;

	void eat() {
		System.out.println("开吃");
	}

	static void speak() {
		System.out.println("小头爸爸");
	}
}

class Son extends Father {
	int x = 3;
	static int y = 4;

	void eat() {
		System.out.println("大头儿子很能吃");
	}

	static void speak() {
		System.out.println("大头儿子。");
	}
}

class Demo {

	public static void main(String[] args) {

		Father f = new Son(); // 父类引用指向了子类对象。
		System.out.println(f.x);
		System.out.println(f.y); 

		f.eat(); 

		f.speak(); 

	}
}

Son类继承父类

1:创建Father f=new Son();

这就是父类引用指向了子类对象。

想想下列问题:

问f.x=?(非静态)   --1

问f.y=?(静态)     --2

问f.eat()输出的是子类还是父类信息?(非静态)----子类

问f.speak()输出的是子类还是父类信息?(静态)----父类

运行效果如图:

那为什么会有这样的结果呢?看下面的总结~

3.总结:

(1)当父类和子类具有相同的非静态成员变量,那么在多态下访问的是父类的成员变量

(2)当父类和子类具有相同的静态成员变量,那么在多态下访问的是父类的静态成员变量

所以:父类和子类有相同的成员变量,多态下访问的是父类的成员变量。

(3)当父类和子类具有相同的非静态方法(就是子类重写父类方法),多态下访问的是子类的成员方法。

(4)当父类和子类具有相同的静态方法(就是子类重写父类静态方法),多态下访问的是父类的静态方法。

4.多态体现-总结:

(1)父类引用变量指向了子类的对象

(2)父类引用也可以接受自己的子类对象

5.多态前提:

类与类之间有关系,继承或者实现

6.多态弊端

提高扩展性,但是只能使用父类引用指向父类成员。

7.多态特点

非静态

(1)编译时期,参考引用型变量所属的类是否有调用的方法,如果有编译通过。没有编译失败

(2)运行时期,参考对象所属类中是否有调用的方法。

(3)总之成员函数在多态调用时,编译看左边,运行看右边。

在多态中,成员变量的特点,无论编译和运行参考左边(引用型变量所属的类)。

在多态中,静态成员函数特点,无论编译和运行都参考左边

8.多态的作用

(1)多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。

  /*    1:定义功能,根据输出任何图形的面积和周长。
		子类重写了父类的抽象方法,多态下,会执行子类的非静态方法。
	2:多态可以作为返回值类型。
		获取任意一辆车对象
	3:抽象类和接口都可以作为多态中的父类引用类型。
*/
abstract class MyShape{
	public abstract double getArea();
	public abstract double getLen();
}
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);
	}

}
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;
	 }
}

class Demo{

	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:定义汽车类,有名字和颜色,提供有参和无参构造,有运行的行为。
 2:定义Bmw类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
 3:定义Benz类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
 4:定义Bsj类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
 5:定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。
 1:使用(int)Math.round(Math.random()*2); 生成0-2之间随机数。
 Math 类
 2:使用if else 判断,指定,0,1,2 new 不同汽车 并返回。
 6:调用该方法,发现多态的好处。
 */
class Car {
	String name;
	String color;

	Car() {

	}

	Car(String name, String color) {
		this.name = name;
		this.color = color;
	}

	void run() {
		System.out.println("跑跑。。。。");
	}
}

class Bmw extends Car {
	Bmw() {

	}

	Bmw(String name, String color) {
		super(name, color);
	}

	void run() {
		System.out.println("宝马很拉风。。。。");
	}
}

class Benz extends Car {
	Benz() {

	}

	Benz(String name, String color) {
		super(name, color);
	}

	void run() {
		System.out.println("奔驰商务首选。。。。");
	}
}

class Bsj extends Car {

	Bsj() {

	}

	Bsj(String name, String color) {
		super(name, color);
	}

	void run() {
		System.out.println("泡妞首选。。。。");
	}
}

class Demo {

	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)抽象类和接口都可以作为多态中的父类引用类型。

看第一个作用的例子~

9.多态类型转换

如何在多态下,使用父类引用调用子类特有方法。

(1)基本类型转换:

自动:小->大

强制:大->小

(2)类类型转换

前提:继承,必须有关系

自动:子类转父类

强转:父类转子类

class Father {

	void method1() {
		System.out.println("这是父类1");
	}

	void method2() {
		System.out.println("这是父类2");
	}
}

class Son extends Father {
	void method1() {
		System.out.println("这是子类1");
	}

	void method3() {
		System.out.println("这是子类3");
	}
}

class Demo {

	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();
	}
}

效果图:

好了,多态就写完了~

时间: 2024-10-23 19:18:51

Java 多态的详解的相关文章

java移位运算符详解[转]

java移位运算符不外乎就这三种:<<(左移).>>(带符号右移)和>>>(无符号右移). 1. 左移运算符 左移运算符<<使指定值的所有位都左移规定的次数. 1)它的通用格式如下所示: value << num num 指定要移位值value 移动的位数. 左移的规则只记住一点:丢弃最高位,0补最低位 如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模.如对int型移动33位,实际上只移动了332=1位. 2)运算规则 按

java 代理模式详解

java 动态代理(JDK和cglib) 设计模式这东东每次看到就明白可过段时间又不能很流利的说出来,今天就用详细的比喻和实例来加深自己的理解(小弟水平不高有不对的地方希望大家能指出来). (1)代理这个词生活中有很多比如在街边卖手机卡.充公交地铁卡的小商店他们都起了代理的作用,java中的代理跟这些小店商的作用是一样的.再比如我想在淘宝上开个服装店但又没有货源怎么办,这时候我就要跟淘宝上某一卖家联系做他的代理.我跟我的商家都要卖衣服(就好比我们都继承了卖衣服的接口sellClothesInte

设计模式 - 迭代器模式(iterator pattern) Java 迭代器(Iterator) 详解

迭代器模式(iterator pattern) Java 迭代器(Iterator) 详解 本文地址: http://blog.csdn.net/caroline_wendy 参考迭代器模式(iterator pattern): http://blog.csdn.net/caroline_wendy/article/details/35254643 Java的标准库(util)中包含迭代器接口(iterator interface), import java.util.Iterator; 继承(

java内存泄露详解

很多人有疑问,java有很好的垃圾回收机制,怎么会有内存泄露?其实是有的,那么何为内存泄露?在Java中所谓内存泄露就是指在程序运行的过程中产生了一些对象,当不需要这些对象时,他们却没有被垃圾回收掉,而且程序运行中很难发现这个对象,它始终占据着内存却没有发挥作用. 我举这样一个例子,在现实开发中我们需要自定义一个先进后出的栈集合,代码如下: 这个代码看起来和运行起来都没问题,但是,这里有个很隐晦的问题,就是在pop()方法里面,我们首先找到集合最后一个元素的下标,然后按照下标从集合中取出,但是这

java移位运算符详解

java移位运算符不外乎就这三种:<<(左移).>>(带符号右移)和>>>(无符号右移).1.左移运算符左移运算符<<使指定值的所有位都左移规定的次数.1)它的通用格式如下所示:value << numnum 指定要移位值value 移动的位数.左移的规则只记住一点:丢弃最高位,0补最低位如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模.如对int型移动33位,实际上只移动了332=1位. 2)运算规则按二进制形式把所有的

Java关键字synchronized详解

Java关键字synchronized详解 博客分类: Java综合 Java多线程thread互联网制造 synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A,没有的话,直接运行 它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法: 通过在方法声明中

转:Java HashMap实现详解

Java HashMap实现详解 转:http://beyond99.blog.51cto.com/1469451/429789 1.    HashMap概述: HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变. 2.    HashMap的数据结构: 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造

Java网络编程详解

Java网络编程详解 http://blog.csdn.net/he90227/article/details/39184247 Java网络编程详解

Eclipse Java Build Path详解

Eclipse Java Build Path详解 1.设置"source folder"与"output folder". * source folder:存放.java源文件的根目录;    * output folder:.class编译输出的根目录:    * 纯“java project”中,一般把"src"设置为source folder,把bin设置为output folder:    * 在“web project”中,一般把&q