Java 学习之路 之 多态 (十三)

Java 引用变量有两个类型:一个是编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现所谓的多态(Polymorphism)。

1,多态性

package com.demo;

class BaseClass{
	public int book = 6;
	public void base(){
		System.out.println("父类的普通方法");
	}
	public void test(){
		System.out.println("父类的被覆盖的方法");
	}
}

public class SubClass extends BaseClass {
	//重新定义一个 book 实例 Field 隐藏父类的 book 实例 Field
	public String book = "java书";
	public void test(){
		System.out.println("子类的覆盖父类的方法");
	}
	public void sub(){
		System.out.println("子类的普通方法");
	}
	public static void main(String[] args) {
		//下面编译时类型和运行时类型完全一样,因此不存在多态
		BaseClass bc = new BaseClass();
		//输出6
		System.out.println(bc.book);
		//下面两次调用将执行BaseClass的方法
		bc.base();
		bc.test();
		//下面编译时类型和运行时类型完全一样,因此不存在多态
		SubClass sc = new SubClass();
		//输出 java书
		System.out.println(sc.book);
		//下面调用将执行从父类继承到的base方法
		sc.base();
		//下面调用将执行当前类的test方法
		sc.test();
		//下面编译时类型和运行时类型不一样,多态发生
		BaseClass ploymophicBc = new SubClass();
		//输出 6 -- 表明访问的是父类 Field
		System.out.println(ploymophicBc.book);
		//下面调用执行从父类继承到的base 方法
		ploymophicBc.base();
		//下面调用将执行当前类的 test 方法
		ploymophicBc.test();
		//因为 ploymophicBc 的编译时类型是 BaseClass
		//BaseClass 类没有提供 sub 方法,所以下面代码编译时出现错误
		//ploymophicBc.sub();
	}
}
6
父类的普通方法
父类的被覆盖的方法
java书
父类的普通方法
子类的覆盖父类的方法
6
父类的普通方法
子类的覆盖父类的方法
上面的程序的 main 方法中显示创建了三个引用变量,对于前两个引用变量bc 和 sc, 它们编译时类型和运行时类型完全相同,因此调用它们的 Field 和方法非常正常,完全没有任何问题。但第三个引用变量 ploymophicBc 则比较特殊,它的编译时类型是BaseClass,而运行时类型是 SubClass,当调用该引用变量的test方法(BaseClass类中定义了该方法,子类SubClass覆盖了父类的该方法)时,实际执行的是 SubClass 类中覆盖后的 test 方法,可就可能不吃按多态了。

相同类型的变量、调用同一个方法时呈现出多种不同的I型能够为特征,这就是多态。

上面的 main 的方法中注释了 ploymophicBc.sub();,这行代码会在编译时引发错我。虽然ploymophicBc 引用变量实际上确实包含 sub() 方法,但因为它的编译时类型为 BaseClass,因此编译时无法调用 sub() 方法。

2,引用变量的强制类型转换

编写 Java 程序是,引用变量值能调用它编译时类型的方法,而不能调用它运行时类型的方法,即使它实际所引用的队形确实包含该方法,如果需要让这个引用变量调用它运行时类型的方法,则必须把他强制类型转换成运行时类型,强制类型转换需要借助于类型转换运算符。

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

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

引用类型支架你的转换只能在具有继承关系的两个类型之间进行,如果是两个没有任何继承关系的类型,则无法进行类型转换,否则编译时会出现错误。

3,instanceof 预算法

instanceof 运算符的前一个操作数通常是一个引用类型变量,后一个操作数通常是一个类(也可以是接口,可以把接口理解成一种特殊的类),它用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是,则返回true,否则返回false。

package com.demo;

public class InstanceofTest {
	public static void main(String[] args) {
		//声明 hello 时使用 Object 类,则hello 的编译类型是 Object
		//Object 是所有类的父类,但hello变量的实际类型是String
		Object hello = "Hello";
		//String 是 Object 类的子类,可以进行 instanceof 运算。返回true
		System.out.println("字符串是否是 Object 类的实例:" + (hello instanceof Object));
		//返回true
		System.out.println("字符串是否是String 类的实例" + (hello instanceof String));
		//Math是Object类的子类,可以进行
		System.out.println("字符串是否是 Math 类的实例:" + (hello instanceof Math));
		//String实现了Comparable接口,所以返回 true
		System.out.println("字符串是否是Comparable接口的实例:" + (hello instanceof Comparable));
		String a = "Hello";
		//String类既不是Math类,也不是Math类的父类
		//所以下面代码编译无法通过
		System.out.println("字符串是否是Math类的实例:" + (a instanceof Math));
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值