1.概述
在Java中,多态是指不同类的对象在调用同一个方法时所呈现的不同行为。通常来说,在一个类定义的属性和方法被其他类继承或重写后,当把子类对象直接赋值给父类引用变量时,相同类型的变量用同一个方法将呈现出多种不同的形态。通过多态,消除了类之间的耦合关系,大大提高了程序的可扩展性和可维护性。
Java的多态性是由继承,方法重写以及父类引用指向子类对象体现的,由于一个父类可以有多个子类,多个子类都可以重写父类的方法,并且多个不同的子类对象也可以指向同一个父类。这样,程序只有在运行的时候才能知道具体代表那个子类对象,这就体现了多态性。
abstract class Animal{
public abstract void shout();
}
class Cat extends Animal{
@Override
public void shout() {
System.out.println("喵喵猫...");
}
}
class Dog extends Animal{
@Override
public void shout() {
System.out.println("汪汪汪...");
}
}
public class test {
public static void main(String[] args) {
Animal cat=new Cat();
Animal dog = new Dog();
cat.shout();
dog.shout();
}
}
在上述代码中,首先创建了两个类Dog和Cat,他们都继承了Animal,在18~22行代码中,分别创建了Cat和Dog两个类对象同时指向了一个父类对象,并调用了shout()方法,程序在编译的时候会自动识别子类对象,从而选择性的调用相应的方法,这就是Java多态性的体现。
2.对象的类型转换
在多态的学习中,涉及到子类对象当作父类类型的情况,这种情况在Java中被称为“向上转型”,例如如下:
//向上转型
Animal cat=new Cat(); //将Cat类对象当作Animal类型来使用
Animal dog=new Dog(); //将Dog类对象当作Animal类型来使用
interface Animal{
//定义抽象方法
public void shout();
}
class Cat implements Animal {
@Override
public void shout() {
System.out.println("喵喵猫...");
}
}
class Dog implements Animal {
@Override
public void shout() {
System.out.println("汪汪汪...");
}
}
public class test {
public static void main(String[] args) {
Animal cat=new Cat();
Animal dog = new Dog();
cat.shout();
dog.shout();
}
}
interface Animal{
//定义抽象方法
public void shout();
}
class Cat implements Animal {
@Override
public void shout() {
System.out.println("喵喵猫...");
}
public void catchMouse(){
System.out.println("小猫抓老鼠....");
}
}
public class test {
public static void main(String[] args) {
Animal an=new Cat();
an.shout();
an.catchMouse();
}
}
在上述截图中,我们发现程序报错了。原因在于,我们在创建Cat对象时指向了Animal父类类型,这样创建的Cat对象会自动向上转型为Animal,然后通过父类对象an分别调用了shout()方法和子类Cat特有的catchMouse()方法,而catchMouse()方法是Cat类特有的,所以通过父类对象调用时,编译就会报错。
由于通过new Cat()创建的对象的本质就是Cat类型,所以通过Cat类型的对象调用catchMouse()方法是可行的,因此要解决上面的问题,可以将父类类型的对象强转为Cat类型,如下:
public class test {
public static void main(String[] args) {
Animal an=new Cat();
//向下转型
Cat an1 = (Cat) an;
an1.shout();
an1.catchMouse();
}
}
interface Animal{
//定义抽象方法
public void shout();
}
class Cat implements Animal {
@Override
public void shout() {
System.out.println("喵喵猫...");
}
public void catchMouse(){
System.out.println("小猫抓老鼠....");
}
}
class Dog implements Animal{
@Override
public void shout() {
System.out.println("汪汪汪...");
}
}
public class test {
public static void main(String[] args) {
Animal an=new Dog();
Cat an1 = (Cat) an;
an1.shout();
an1.catchMouse();
}
}
上述代码在编译时正常,但是在运行的时候就会报错,提示出上述截图的错误。出错的原因是,创建的Animal对象本质时一个Dog对象,在强制转换类型的时候,Dog类型的对象显然无法强转为Cat类型。
为了避免上述这种异常情况的发生, Java提供了一个关键字instanceof,它可以判断一个对象是否为某个类(或接口)的实例或者子类实例,其语法格式如下:
对象(或者对象引用变量) instanceof 类(或接口)
instanceof 是 Java 中的一个双目运算符,由于它是由字母组成的,所以也是 Java 的保留关键字
- 作用是:测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
- instanceof是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。
- 说明下:类的实例包含本身的实例,以及所有直接或间接子类的实例
- instanceof左边显式声明的类型与右边操作元必须是同种类或存在继承关系,也就是说需要位于同一个继承树,否则会编译错误
下面是对上述代码的修改:
public class test {
public static void main(String[] args) {
Animal an=new Dog();
if(an instanceof Cat){
Cat an1 = (Cat) an;
an1.shout();
an1.catchMouse();
}else {
System.out.println("该类型不是Cat类型!");
}
}
}