什么是多态
在同一个方法中,这种由于参数类型不同而导致执行效果各异的现象就是多态。继承是多态得以实现的基础
在Java中,为了实现多态,允许使用一个父类类型的变量来引用一个字类类型的对象,根据被引用子类对象特征的不同,得到不同的运行结果。
interface Anmal{ void show(); //抽象类,抽象方法 } class Cat implements Anmal{ @Override public void show() { //实现抽象方法 System.out.println("我是一只猫,喵喵喵喵"); } } class Dog implements Anmal{ @Override public void show() { System.out.println("我是一只狗,旺旺旺旺"); } } public class Example01 { public static void main(String[] args) { Anmal cat = new Cat(); //创建Cat对象 Anmal dog = new Dog(); //创建Dog对象 animalshow(cat); animalshow(dog); } //定义静态的animalshow方法,接收一个Animal类型的参数 public static void animalshow(Anmal an) { an.show(); } }
多态不仅解决了方法同名的问题,而且还使程序变得更加灵活,从而有效地提高了程序的可扩展性和可维护性
对象的类型转换
在多态的学习中,涉及到将子类对象当做父类类型使用的事情,此钟情况在Java的语言环境中称为"向上转型",例如以下两行代码
Animal an1 = new Cat(); //将Cat对象当做Animal类型来使用 Animal an2 = new Dog(); //将Dog对象当做Animal类型来使用
将子类对象当做父类使用时不需要任何显式的声明,需要注意的是,此时不能通过父类变量去调用子类中的特有方法
将父类类型的变量强制转为子类类型:
public static void animalshow(){ Cat cat = (Cat) animal; //将animal对象强制转换为Cat类型 cat.show() //调用cat的show()方法 cat.sleep() //调用cat 的sleep()方法 }
这种父类型当做子类型使用的情况,在Java的语言环境中被称为"向下转型"。
Java提供一个instanceof关键字,它可以判断一个对象是否为某个类(或接口)的实例或者子类实例,语法格式如下:
对象(或者对象引用变量) instanceof 类(接口)
示 例:
public static void animal(Animal animal){ if(animal instanceof Cat ){ //判断animal是否是Cat类的实例对象 Cat cat = (Cat) animal; //animal强转为Cat类型 cat.sleep(); //调用Cat的sleep()方法 cat.show(); //调用Cat的show()方法 }else{ System.out.println("this animal is not a cat"); }
使用instanceof关键字判断animalshow()方法中传入的对象是否为Cat类型,如果是Cat类型就进行强制类型转换,否则就打印"this animal is not a cat"
Object类
在JDK中提供了一个Object类,它是类层次结果的根类,每个类都直接或间接继承自该类。所有对象(包括数组)都实现了这个类的方法
equals() 指示其他某个对象是否与此对象"相等"
getClass() 返回此Object的运行时类
hashCode() 返回该对象的哈希码值
toString() 返回该对象的字符串表示
在实际开发中,通常希望对象的toString()方法返回的不仅仅是基本信息,而是一些特有的信息。这时重写Object的toString()方法便可以实现
class Animal{ //重写Object类的toString()方法 public String toString() { return "这是一个动物"; } } public class Example01 { public static void main(String[] args) { Animal animal = new Animal(); //创建Animal类对象 System.out.println(animal.toString()); //调用toString方法 } }
匿名内部类
在编写Java程序时,在类里面定义的类称之为内部类(Inner Class),内部类是外部眼泪第一个成员。Java内部类可以分为成员内部类、方法内部类和匿名内部类等
在多态的讲解中,如果方法的参数被定义为一个接口类型,那么就需要定义一个类来实现接口,并根据该类进行对象实例化。除此之外,还可以使用匿名内部类来实现接口。当程序中使用匿名内部类时,在定义匿名内部类的地方往往直接创建该类的一个对象。匿名内部类是实现接口垫 一种简便写法。
普通内部类实现方式:
interface Animal{ void show(); //定义抽象方法show() } //定义测试类 public class Example01 { public static void main(String[] args) { //定义一个内部类Cat实现Animal接口 class Cat implements Animal{ @Override public void show() { System.out.println("嘻嘻..."); } } animalshow(new Cat()); //调用animalshow()方法并传入Cat对象 } public static void animalshow(Animal an) { an.show(); } }
匿名内部类的格式:
new 父类(参数列表) 或 父接口(){ //匿名内部类实现部分 }
匿名内部类实现方式:
//定义动物类接口 interface Aniaml{ void show(); } public class Example01 { public static void main(String[] args) { //定义匿名内部类作为参数传递给animalshow()方法 animalshow(new Aniaml() { @Override public void show() { System.out.println("喵喵喵喵..."); } }); } //定义静态方法animalshow{} private static void animalshow(Aniaml an) { an.show(); } }
分两步来编写匿名内部类,具体如下:
1. 在调用animalshow()方法时,在方法的参数位置写上new Aniaml(){},这相当于创建了一个实例对象,并将对象作为参数传给animalshow()方法。在new Aniaml()后面有一对大括号,表示创建的对象为Aniaml的子类实例,该子类是匿名的。
animalshow(new Animal(){});
2. 在大括号中编写匿名子类的实现代码
animalshow(new Aniaml() { @Override public void show() { System.out.println("喵喵喵喵..."); } });