多态,简单来说就是一种类型表现出多种状态。在Java中多态分为两类。
一、方法多态性——方法的重载和重写。
关于这部分内容已经在前面的内容有过详细的记录,即重复调用的代码块—方法和面向对象的特性之二—继承。
二、对象的多态性——引用类型转换。
1.向上转型(自动转型)——子类对象自动转换为父类对象。
1 class Father 2 { 3 public void speak() 4 { 5 System.out.println("我来自父类Father。"); 6 } 7 } 8 class Son extends Father 9 { 10 public void speak() 11 { 12 System.out.println("我来自子类Son。"); 13 } 14 } 15 class Daughter extends Father 16 { 17 public void speak() 18 { 19 System.out.println("我来自子类Daughter。"); 20 } 21 } 22 public class T02 23 { 24 public static void main(String[] args) 25 { 26 Father p; 27 Son s = new Son(); 28 Daughter d = new Daughter(); 29 p=s;//子类对象向上类型转换为Father类型 30 p.speak(); 31 p=d; 32 p.speak(); 33 } 34 }
输出结果如下:
我来自子类Son。
我来自子类Daughter。
可以看出,第26行声明了一个父类对象p,但没有实例化;第27、28行分别声明子类对象s、d并实例化;经过赋值操作,将子类对象向上转型为Father类型。通过p调用其speak方法,实际输出的是子类对象的speak方法。这里就体现了多态性思想。
需要注意的是:上述父类对象只能调用被子类重写的方法,对于子类自己独有的方法,父类对象是无法访问的。
1 class Father 2 { 3 public void speak() 4 { 5 System.out.println("我来自父类Father。"); 6 } 7 } 8 class Son extends Father 9 { 10 public void speak() 11 { 12 System.out.println("我来自子类Son。"); 13 } 14 public void print() 15 { 16 System.out.println("我是Tom。"); 17 } 18 } 19 public class T02 20 { 21 public static void main(String[] args) 22 { 23 Father p; 24 Son s = new Son(); 25 p=s;//子类对象向上类型转换为Father类型 26 p.speak(); 27 p.print();//错误的,无法访问 28 } 29 }
那么如果非要调用子类的print()方法,那么就要用到下面的向下强制转型,将父类对象赋值给子类对象。
2.向下转型(强制转型)——父类对象强制转换为子类对象。
1 class Father 2 { 3 public void speak() 4 { 5 System.out.println("我来自父类Father。"); 6 } 7 } 8 class Son extends Father 9 { 10 public void speak() 11 { 12 System.out.println("我来自子类Son。"); 13 } 14 public void print() 15 { 16 System.out.println("我是Tom。"); 17 } 18 } 19 public class T02 20 { 21 public static void main(String[] args) 22 { 23 Father p = new Son(); 24 p.speak();//自动类型转换 25 ((Son) p).print();//强制类型转换 26 } 27 }
如果同时存在多个子类,就需要使用instanceof关键字来检测转换的安全性,即在每次转换之前都加上一个if判断语句:
if(p instanceof Son) { Son s1 = (Son)p(); }else { System.out.println("无法转换!"); }
3.隐藏——static无法被重写的特性。
当我们不想调用子类中重写的方法,而希望调用父类中原来的方法时,就可以使用隐藏来实现。
1 class Father 2 { 3 public static void speak() 4 { 5 System.out.println("我来自父类Father。"); 6 } 7 } 8 class Son extends Father 9 { 10 public static void speak() 11 { 12 System.out.println("我来自子类Son。"); 13 } 14 } 15 public class T02 16 { 17 18 public static void main(String[] args) 19 { 20 Father p = new Son(); 21 p.speak();//调用的是父类中的speak()方法 22 } 23 }
输出结果:我来自父类Father。