多态性的理解和应用
1.1. 多态性的理解
多态性:在Java中,多态性是它的一大特性,可以理解成为是事物的多种形态。
广义上的多态性包括了:
1.方法的重写:子类在继承父类的时候会继承它所有的内部结构,但是由于自身的属性或者独有的功能,需要对方法进行改写
2.子类对象的多态性:表示子类的对象赋值给父类的引用【父类的引用指向子类的对象】
1.2 多态性的运用
多态性在平时开发中的应用,通常我们不会直接声明一个父类然后将其赋值给子类,这样会可能导致一些类型的错误转换,比如刻意声明一个跟子类毫不相干的类,这样就会造成编译错误。
public class Account{
public static void main{
Account acct = new CheckAccount();
}
}
class CheckAccount extends Account{
}
编译时,引用变量acct只能调用其父类声明的方法,因为编译器认为它是一个Account类,也就是声明什么类,编译器会把它当成什么类,但是当运行时,他只会调用的是子类对于父类重写的方法,若没有重写,其实本质上是调用子类的方法,因为在new 对象的时候,还是将acct的属性存放在堆里,以及实际调用的是子类的栈中的方法。
因此也就是编译看左边,运行看右边。
额外补充:
方法区存放的是字节码文件,堆存放的是对象和容器,栈中存放的是方法和成员变量,java把内存分两种:一种是栈内存,另一种是堆内存1。在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;2。堆内存用来存放由new创建的对象和数组以及对象的实例变量 在函数(代码块)中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由java虚拟机的自动垃圾回收器来管理
Tips;子类对象的多态性的使用前提:首先是要有子类的继承性,以及方法的重写。子类对象的多态性不适用于属性、构造器。
其实也可以把子类对象的多态性理解成为是向上转型,也就是向上自动提升类型,最终只是为了实现虚方法调用(Virtual Method)。也就是子类对象对父类的引用进行赋值之后,在编译时我们只能调用父类的方法,如果调用子类独有的方法则会编译报错,但是当运行时,我们返回的结果是运行了子类方法之后的结果。
代码举例
举例一:
class Customer{
private Account acct;
public void setAccount(Account acct){ //Account acct = new CheckAccount()
this.account = account;
}
}
class Account{
double balance;
存钱、取钱
}
class SavingAccount extends Account{}
class CheckAccount extends Account{}
举例二:
java.lang.Object类中定义的方法:
public boolean equals(Object obj){}
举例三:使用jdbc技术操作数据库:mysql\oracle\db2\sqlserver\....
比如:jdbc中涉及一个父类:Connection。
及其内部的一些关于操作数据库的通用方法。
public void operateData(Connection conn){
//通过conn获取连接、传送sql语句、执行、....
}
1.3 多态性的相关使用
向下转型,跟基本数据类型一样,可以自动提升和进行强转化,Object类也可以向上转型和向下转型,
向下转型说的是将声明为父类引用的子类对象,通过强转化的方法,将父类的引用再转换为子类的引用
代码举例
//如果Person是Man和Woman的父类,
//同时goshopping和isBeauty是woman这个类独有的方法
public static void main(String[] args){
Person p = new Man();
Man m = (Man)m;
强转时,可能出现类型转换异常:ClassCastException
Woman w1 = (Woman)p;
w1.goShopping();
w1.isBeauty = true;
【因为它的本质还是属于Man,那我们运行的只能是子类Man的方法】
向下转型中,为了避免在强转时出现ClassCastException,我们在强转前,使用instanceof 进行判断即可。
格式:a instanceof A:判断对象a是否是类型A的一个实例。 如果是,返回true。如果不是,返回false。 补充:如果a instanceof A返回true,则a instanceof B也一定返回true。其中,类型B是类型A的父类。
1.4 多态性的实际编写
通常在使用多态性的时候会出现三种情况:
1.编译不通过
String str =new Date();
这种主要是因为Date类和String是并行的类,或者说它们并没有继承关系。
2.编译通过,运行不通过
Object obj = new Date();
String str = (String) obj;
同样的道理,这里不能向下转型为跟Date没有关系的类,
或者说他不是子父类的关系,
3.编译运行都通过
Object obj = new Man();
Person p = (Person)obj;
其实整个向下转型主要说的是把父类的声明引用指向子类之后,又回到子类的声明。
网友评论