**
初学Java多态 学习笔记
**
简单来说,多态:父类型的引用可以指向子类型的对象,或者接口类型的引用可以指向实现该接口的类的实例 。多态是运行器的行为,有晚绑定的特征。所谓晚绑定,就是程序运行过程中,编译器只知道编译过程中引用变量是什么类型的,而并不知道它指向了什么类型的对象。直到运行时,它才知道自己指向的是哪个类的实例对象。
public class PolyTest
{
public static void main(String[] args)
{
/*
Parent parent = new Parent();
parent.sing();
Child child = new Child();
child.sing();
*/
Parent p = new Child();
p.sing();
}
}
class Parent
{
/*
public void sing()
{
System.out.println("parent is singing");
}
*/
}
class Child extends Parent
{
public void sing()
{
System.out.println("child is singing");
}
}
Parent p = new Child();当使用多态方式调用方法时,首先检查父类中是否有sing()方法,如果没有则编译错误;如果有,再去调用子类的sing()方法。什么类型的引用就能调用什么类型的方法。
多态的用途
引用在程序运行时才确定具体指向的实例类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
public class PolyTest5
{
// 普通方法调用还要在PolyTest5类中增加方法,以接收不同类型的引用
/*
public void run(BMW bmw)
{
bmw.run();
}
public void run(QQ qq)
{
qq.run();
}
*/
// 使用多态的方法,直接接收 Car 类型,调用 Car 类型的 run() 方法
public void run(Car car)
{
car.run();
}
public static void main(String[] args)
{
/*
PolyTest5 test = new PolyTest5();
BMW bmw = new BMW();
test.run(bmw);
QQ qq = new QQ();
test.run(qq);
*/
PolyTest5 test = new PolyTest5();
Car car = new BMW();
// 将 car 赋给 Car 类型的引用,
test.run(car);
QQ qq = new QQ();
//将 QQ 类型的引用赋给 Car 类型的引用,相当于向上类型转换。
test.run(qq);
}
}
class Car
{
public void run()
{
System.out.println("car is running");
}
}
class BMW extends Car
{
public void run()
{
System.out.println("BMW is running");
}
}
class QQ extends Car
{
public void run()
{
System.out.println("QQ is running");
}
}
假如有一百辆车,都需要调用他们的 run() 方法,那就需要生成一百个类,这是必不可少的,那么我们可以怎么简单一点的去调用所有车的 run() 方法呢?如果是用普通的方法调用的话,每增加一个子类,不仅子类中需要增加方法,还要在PolyTest5类中增加方法,这就过于繁琐了。
不如这样,写一个方法就能处理所有的情况。因为所有的车都继承了 Car 这个父类,在 PolyTest5 中写一个接收 Car 类型引用的方法,在 main() 中不管生成 Car 类型的引用还是 qq 这种具体子类型的引用,接收 Car 类型引用的方法都可以通过接收这个引用的值,从而调用他们的 run() 方法,这样,就使程序更加简洁了。
多态具体解释
所谓多态,就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
–转自 博客园chenssy
父类与子类之间的两种类型转换
① 向上类型转换(upcast): 将子类转换为父类型,对于向上类型转换不需要显式指定。
② 向下类型转换(downcast):将父类型转换为子类型,对于向下类型转换必须要显式指定(必须要使用强制类型转换)。必须满足父类型引用指向的对象是子类型实例化对象。
public class PolyTest2
{
public static void main(String[] args)
{
/*
Animal animal = new Cat();
Animal animal2 = new Animal();
animal2 = animal;
animal2.sing();
*/
/*
Animal animal = new Cat();
Animal animal2 = new Animal();
animal = animal2;
animal.sing();
*/
/*
Cat cat = new Cat();
Animal animal = cat;//父类型的引用指向子类型的对象
animal.sing();
*/
/*
Animal animal = new Animal();
Cat cat = (Cat)animal;
*/
//向上类型转换
Cat cat = new Cat();
Animal animal = cat;//或者Animal animal = (Animal)cat;
animal.sing();
//向下类型转换
Animal a = new Cat();
Cat cat = (Cat)a;//不能写为 Cat cat = a; 必须在括号中显式地写出具体指向的是哪个类型的对象
cat.sing();
}
}
class Animal
{
public void sing()
{
System.out.println("animal is singing!");
}
}
class Dog extends Animal
{
public void sing()
{
System.out.println("dog is singing!");
}
}
class Cat extends Animal
{
public void sing()
{
System.out.println("cat is singing!");
}
}
1.子类可以自动向上转换成父类型,只是部分内存空间无法访问,只能访问父类型在子类中的方法和变量
2.父类型向下转换成子类型,必须满足父类型变量是子类型实例化对象,其实也就是原本一个子类实例,先自动向上转换成父类型,内存空间并没有丢失,当然可以再转换回来