目录
多态(ploymorphism)
【定义】Java引用变量有两种类型:一种是编译时类型,另一种是运行时类型。如果编译时类型和运行时类型不一致时,就能出现所谓的多态。即同一个类型的变量,在执行同一个方法时,表现出多种行为特征。
【多态的类型】Java的引用变量,有两个类型
- 编译时类型:有声明他的类型决定
- 运行时类型:由该引用实际指向的对象来决定
由于有如下关系:父类到子类是从一般到特殊的关系 —— 如,Animal an = new Wolf();
上面创建新对象的过程可以理解为:an是一种animal,哦~ 原来an是狼(前父后子的格式)
【得到第一个结论】子类的实例完全可以当成父类对象使用。父类的引用变量完全可以指向子类的实例。
class BaseClass {
public int a = 5;
public void base() {
System.out.println("父类的普通方法");
}
public void test() {
System.out.println("父类的被覆盖方法");
}
}
public class SubClass extends BaseClass {
// 重新定义一个a的实例变量隐藏父类的a实例变量
public String a = "这是子类的字符串";
public void test() {
System.out.println("这是子类覆盖父类的方法");
}
public void sub() {
System.out.println("这是子类的普通方法");
}
public static void main(String[] args) {
// 下面编译时类型和运行时类型完全一样,因此不存在多态
BaseClass bc = new BaseClass();
// 下面代码的输出结果为5
System.out.println(bc.a);
// 下面两次调用BaseClass类中的两个方法
bc.base();
bc.test();
// 下面编译时类型和运行时类型完全一样,因此不存在多态
SubClass sc = new SubClass();
// 下面代码的输出结果为"这是子类的字符串"
System.out.println(sc.a);
sc.base();
sc.test();
//下面代码编译时和运行时类型不一样,会出现多态。
//编译时ploy的类型为BaseClass,运行时的类型为SubClass
BaseClass ploy = new SubClass();
ploy.base();
ploy.test();
// ploy的编译时类型是BaseClass
// 因为BaseClass类中没有sub()方法,所以下面代码编译时会出现错误
// ploy.sub;
}
}
运行结果:
【分析代码】
- 分析最后多态是的代码,ploy在SubClass类中没有base()方法,所以只能向上找它的直接父类,寻找base()方法;而SubClass类中有test()方法,且运行时的类型是SubClass类型(当然编译时是BaseClass类型且存在BaseClass类,所以编译能通过),所以会调用SubClass中的方法,即覆盖了父类方法的子类中的方法。
- ploy的编译时类型是BaseClass,因为BaseClass类中没有sub()方法,所以这条代码编译时会出现错误ploy.sub。
【多态的意义】多态增加了Java语言的灵活性,也是和设计模式紧密相连的
当我们调用引用变量时,他总是呈现它的运行时类型的特征
在编译阶段,编译器并不知道引用变量实际所引用的对象类型,编译器只知道它编译时类型。
========================================================================================
变量引用的强制类型转换
在Java程序中,引用变量只能调用它编译时类型的方法,而不能调用它运行时的方法,即使它实际所引用的变量确实包含该方法,这也也是不行的,一定要编译时,也就是引用类型一定要有该方法。
强制类型转换的运算符是(类型):
- 基本类型之间(除了Boolean之外),都可以进行转换
- 引用类型之间,只能在具有继承关系的两个类型之间转换
- 在强制类型转换中,使用instanceof运算符可以让强制类型转换更安全
【最有名的异常】
- NullPointerException(空指针异常)
- ArrayIndexOutofBoundsException(数组索引边界溢出异常)
- ClassCastException(类抛出异常,即是类型转换错误)
========================================================================================
instanceof 运算符
【定义】instanceof运算符的前一个操作数通常是一个引用类型变量,后一个操作数通常是一个类(也可以是一个接口,可以把接口看作是一种特殊的类),它用于判断前面对象是否是后面对象的类,或者子类、实现类中的实例。如果是,返回true;否则,返回false。
【注意】前后类型要么和后面类型相同,要么和后面类型存在父子继承关系
public class InstanceofTest {
public static void main(String[] args) {
//Object类是所有类的父类,obj的实际类型是String
Object obj = "这是instanceof 运算符测试现场";
System.out.println(obj instanceof Object);
System.out.println(obj instanceof String);
System.out.println(obj instanceof Math);
//Comparable接口实例
System.out.println(obj instanceof Comparable);
}
}
运行结果: