多態是一個之前一直搞不清楚的概念,通過這次筆記,對多態的概念及應用有了較全面的認識,同時學習了instanceof關鍵字以及Object類的特點.
1. Java中類的多態
所謂類的多態性,是指子類對象和父類對象之間的相互轉換. 這裡分為兩部分做筆記:
1.1 子類對象向父類對象轉換(向上轉換)
子類對象向父類對象的轉換是自動轉換.格式為: 父類對象 = 子類對象.
這裡需要注意的一點事: 子類對象轉換為父類對象後,所調用的方法一定會是子類複寫後的方法而非父類原有方法.
例如下面的例子:
class Person{public void fun1(){System.out.println("Person -------> public void fun1() ");}public void fun2(){//fun2()調用的是fun1()的方法this.fun1();}}class Student extends Person{//複寫Person類中的fun1()方法public void fun1(){System.out.println("Student -------> public void fun1()");}public void fun3(){System.out.println("Student -------> public void fun1()");}}public class Demo01{public static void main(String args[]){//聲明一個父類對象//new Student()是執行個體化一個子類對象,向父類對象轉換//子類對象向父類對象轉換之後,所調用的方法一定是子類複寫後的方法Person p = new Student();p.fun1();p.fun2(); //這裡也是通過this.fun2()調用的子類複寫後的方法fun1()}}
1.2 父類對象向子類對象轉換(向下轉換)
父類對象向子類對象的轉換是強制轉換. 格式為: 子類對象 = (子類名稱) 父類對象
在父類對象向子類對象的轉換的過程中,需要注意的是: 如果父類對象是執行個體化的父類對象而不是用子類對象轉換過來的對象,則不能在強制轉換為子類對象,否則會出現ClassCastException類轉換異常. 也就是說,能進行父類對象向子類對象轉換的前提是: 之前是使用子類對象的執行個體來初始化得父類對象. 例如下面例子中,是先使用執行個體化的子類對象轉換為父類對象的.
class Person{public void fun1(){System.out.println("Person -------> public void fun1() ");}public void fun2(){//fun2()調用的是fun1()的方法this.fun1();}}class Student extends Person{//複寫Person類中的fun1()方法public void fun1(){System.out.println("Student -------> public void fun1()");}public void fun3(){System.out.println("Student -------> public void fun1()");}}public class Demo02{public static void main(String args[]){//聲明一個父類對象, new Student()是執行個體化一個子類對象,該子類執行個體化對象向父類對象轉換//父類對象向子類對象的轉換,必須經過強制轉換./* 注意: 若父類對象是執行個體化為父類對象而不是下例中用子類對象執行個體化後轉換為父類對象,那這時候就不能再強制轉換為子類對象了,否則會有ClassCastException類轉換異常 */Person p = new Student();Student s = (Student) p;s.fun3();s.fun1();}}
結論:
在進行向下轉換之前,兩個對象必須先發生向上轉換關係(如上面例子),否則無法轉換(出現類轉換異常).
2. instanceof關鍵字
instanceof用於判斷某個對象是否是某個類的執行個體. 例如: a instanceof B 若a是B的執行個體,則返回true,否則返回的是false.
instanceof的使用時機:
例如下例,一般情況下, 都是在轉型之前使用instanceof進行一下判斷,這樣可以進行比較安全的類型轉換.
class A{public void fun1(){System.out.println("A --> public void fun1()") ;}public void fun2(){// fun2方法調用的是fun1方法this.fun1() ;}}class B extends A{// 覆寫A類中的fun1()方法public void fun1(){System.out.println("B --> public void fun1()") ;}public void fun3(){System.out.println("B --> public void fun3()");}}class C extends A{// 覆寫A類中的fun1()方法public void fun1(){System.out.println("C --> public void fun1()") ;}public void fun5(){System.out.println("C --> public void fun5()");}}public class Demo03{public static void main(String args[]){fun(new C()) ;}/* 如果傳入的是B類的對象,則要求再調用fun3()方法;如果傳入的是C類的對象,則要求再調用fun5()方法。這樣,通過instanceof,實現了判別某個對象到底是誰的執行個體 */public static void fun(A a){a.fun2() ;//如果a是B的執行個體化對象,則調用fun3()if(a instanceof B){B b = (B)a;b.fun3() ;}//如果a是B的執行個體化對象,則調用fun5()if(a instanceof C){C c = (C)a ;c.fun5() ;}}}
3. Object類
所有的類都繼承自Object類,這是所有類的一個基類.
一個比較好的類,需要複寫Object類中的三個方法.
|- public String toString()
|- public boolean equals(Object obj)
|- public int hashCode()
在下面的例子中,類Student複寫了上面的toString()方法和equals()方法,而且使用到了instanceof關鍵字,算是一個小複習題目了~
class Student //任意類都是繼承了Object類,最好複寫裡面的toString()和equals()方法{private String name;private int age;public Student(String name,int age){this.name = name;this.age = age;}//複寫Object類中的toString()方法,實現自訂toString()public String toString(){return "該學生的姓名是: "+name+",該學生的年齡是: "+age;}//複寫Object類中的equals()方法,注意,Object類中equals()接收的是Object對象public boolean equals (Object obj){//如果被比較對象和比較對象的記憶體位址都是一樣的,那肯定是同一對象//注意: 記憶體位址的比較使用"=="if (this == obj){return true;}else{//如果obj不是Student的執行個體,肯定不相等了,返回false;if(!(obj instanceof Student)){return false;}else{//走到這步,說明obj是Student的執行個體對象,進行類型轉換後對比之Student stu = (Student) obj;if(this.name.equals(stu.name)&&this.age == stu.age){return true;}else{return false;}}}}}public class Demo04{public static void main(String args[]){Student stu1 = new Student("newsainton",23);Student stu2 = new Student("newsainton",23);//使用toString()方法輸出stu1對象System.out.println(stu1.toString());//使用toString()方法輸出stu2對象System.out.println(stu2.toString());//比較stu1和stu2是否相等System.out.println("比較stu1和stu2是否相等: "+ stu1.equals(stu2));}}