Java面向物件(五)
目錄- Java面向物件(五)
- 十六、面向物件特征之三: 多型性
- 16.1 多型性的定義:
- 16.2 多型性的使用:
- 16.3 多型典型例題
- 十七、instanceof 關鍵字
- 17.1 instanceof 的引入:
- 17.2 instanceof 的使用:
- 17.3 向下轉型和向上轉型拓展
- 十八、Object 類的使用
- 18.1 Object 類介紹
- 18.2 == 與 equals() 方法
- 18.2.1 == 運算子
- 18.2.2 equals() 方法的使用
- 18.2.3 重寫 equals() 方法
- 18.3 toString() 方法
- 十六、面向物件特征之三: 多型性
十六、面向物件特征之三: 多型性
16.1 多型性的定義:
-
物件的多型性:父類的參考指向子類的物件(或子類的物件賦給父類的參考),
可以直接應用在抽象類和介面上,
-
Java 參考變數有兩個型別:編譯時型別和運行時型別,
編譯時型別由宣告該變數時使用的型別決定,運行時型別由實際賦給該變數的物件決定,
簡稱:編譯時,看左邊;運行時,看右邊,
-
若編譯時型別和運行時型別不一致,就出現了物件的多型性,
public class Person {
......
}
public class Man extends Person{
......
}
public class Weman extends Person{
......
}
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person();
Man man = new Man();
//物件的多型性:父類的參考指向子類的物件
//編譯時宣告了一個Person型別的變數p2,運行時實際參考的是Man型別的實體物件
//所以,當呼叫子父類同名同引數的方法時,實際執行的是子類重寫父類的方法 ---虛擬方法呼叫
Person p2 = new Man();
Person p3 = new Woman();
}
}
16.2 多型性的使用:
-
虛擬方法呼叫(Virtual Method Invocation):
-
正常方法呼叫:
Person e = new Person(); e.getInfo(); Student e = new Student(); e.getInfo(); -
虛擬方法呼叫(多型情況下):
子類中定義了與父類同名同引數的方法,在多型情況下,將此時父類的方法稱為虛擬方法,父類根據賦給它的不同子類物件,動態呼叫屬于子類的該方法,這樣的方法呼叫在編譯期是無法確定的,
Person e = new Student(); e.getInfo(); //呼叫Student類的getInfo()方法 /* 編譯時e為Person型別,而方法的呼叫是在運行時確定的,所以呼叫的是Student類的getInfo()方法,——動態系結 */
-
-
多型性的使用前提:① 類的繼承關系 ② 方法的重寫
-
物件的多型性,只適用于方法,不適用于屬性(屬性值編譯和運行都看左邊),
-
多型性使用舉例:
import java.sql.Connection; //多型性的使用舉例一: public class AnimalTest { public static void main(String[] args) { AnimalTest test = new AnimalTest(); test.func(new Dog()); //輸出:狗進食 狗叫 test.func(new Cat()); //輸出:貓進食 貓叫 } public void func(Animal animal){ //Animal animal = new Dog(); animal.eat(); animal.shout(); } } class Animal{ public void eat(){ System.out.println("動物:進食"); } public void shout(){ System.out.println("動物:叫"); } } class Dog extends Animal{ public void eat(){ System.out.println("狗進食"); } public void shout(){ System.out.println("狗叫"); } public void watchDoor(){ System.out.println("狗看門"); } } class Cat extends Animal{ public void eat(){ System.out.println("貓進食"); } public void shout(){ System.out.println("貓叫"); } } //舉例二: class Order{ public void method(Object obj){ } } //舉例三:資料庫連接 class Driver{ public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection(); //規范的步驟去操作資料 // conn.method1(); // conn.method2(); // conn.method3(); } }
16.3 多型典型例題
public class InterviewTest1 {
public static void main(String[] args) {
Base1 base = new Sub1();
base.add(1, 2, 3); //輸出:sub_1
Sub1 s = (Sub1)base;
s.add(1,2,3); //輸出:sub_2
}
}
class Base1 {
public void add(int a, int... arr) {
System.out.println("base1");
}
}
class Sub1 extends Base1 {
public void add(int a, int[] arr) {
System.out.println("sub_1");
}
public void add(int a, int b, int c) {
System.out.println("sub_2");
}
}
// public void add(int a, int... arr) 和 public void add(int a, int[] arr) 是方法重寫,
十七、instanceof 關鍵字
17.1 instanceof 的引入:
-
有了物件的多型性以后,該物件實體在記憶體中不僅加載了父類的屬性和方法,實際上是加載了子類特有的屬性和方法的,但是由于變數宣告為父型別別,導致編譯時,只能呼叫父類中宣告的屬性和方法,子類特有的屬性和方法不能呼叫,
-
如何才能呼叫子類特有的屬性和方法?
向下轉型:使用強制型別轉換符,
Person p2 = new Man();
//p2變數宣告為 Person 型別,不能呼叫子類 Man 類特有的方法
//p2.earnMoney();
//p2.isSmoking = true;
//向下轉型
Man m1 = (Man)p;
m1.earnMoney();
m1.isSmoking = true;
//使用強轉時,可能出現ClassCastException的例外,
// Woman w1 = (Woman)p2; 編譯通過,運行報錯,
// p2變數是一個Person型別的變數,但定義時new的是Man型,實際上指向Man型的物件
// w1.goShopping();
- 為了避免在向下轉型時出現 ClassCastException 的例外,我們在向下轉型之前,先進行 instanceof 的判斷,一旦回傳 true,就進行向下轉型,如果回傳 false,不進行向下轉型,
//問題一:編譯時通過,運行時不通過
//舉例一:
// Person p3 = new Woman();
// Man m3 = (Man)p3;
//舉例二:
// Person p4 = new Person();
// Man m4 = (Man)p4;
//問題二:編譯通過,運行時也通過
// Object obj = new Woman();
// Person p = (Person)obj;
//問題三:編譯不通過
// Man m5 = new Woman();
// String str = new Date();
// 總結:可以這么理解,子類在創建時會加載所有的父類,轉型也只能在已加載的類之間相互轉型,
// 否則,就算是編譯不報錯,運行也會報錯!
17.2 instanceof 的使用:
-
a instanceof A:判斷物件a是否是類A的實體,如果是,回傳 true;如果不是,回傳 false,
-
當類B是類A的父類,
如果 a instanceof A 回傳 true,則 a instanceof B 也回傳 true,
public class Person extends Object {…}
public class Student extends Person {…}
public class Graduate extends Person {…}
public void method1(Person e) {
if (e instanceof Person)
// 處理Person類及其子類物件
if (e instanceof Student)
//處理Student類及其子類物件
if (e instanceof Graduate)
//處理Graduate類及其子類物件
}
17.3 向下轉型和向上轉型拓展
-
從子類到父類的型別轉換可以自動進行,
-
從父類到子類的型別轉換必須通過造型(強制型別轉換)實作,
-
無繼承關系的參考型別間的轉換是非法的,(型別轉換例外)

十八、Object 類的使用
18.1 Object 類介紹
-
Object 類是所有 Java 類的根父類,
-
如果在類的宣告中未使用 extends 關鍵字指明其父類,則默認父類為 java.lang.Object 類,
-
Object 類中的功能(屬性、方法)就具有通用性,
? 屬性:無
? 方法:equals(),toString() ,getClass(),hashCode(),clone(),finalize(),wait(),notify(),notifyAll(),
- Object 類只宣告了一個空參的構造器,
18.2 == 與 equals() 方法
18.2.1 == 運算子
-
可以使用在基本資料型別變數和參考資料型別變數中,
-
如果比較的是基本資料型別變數:比較兩個變數保存的資料是否相等,(不一定型別要相同)
public class EqualsTest { public static void main(String[] args) { //基本資料型別 int i = 10; int j = 10; double d = 10.0; System.out.println(i == j);//true System.out.println(i == d);//true char c = 10; System.out.println(i == c);//true char c1 = 'A'; char c2 = 65; System.out.println(c1 == c2);//true } }
? 如果比較的是參考資料型別變數:比較兩個物件的地址值是否相同.即兩個參考是否指向同一個物件物體,
補充: == 符號使用時,必須保證符號左右兩邊的變數型別一致,
18.2.2 equals() 方法的使用
1. 是一個方法,而非運算子,
2. 只能適用于參考資料型別,
3. Object類中equals()的定義:
public boolean equals(Object obj) {
return (this == obj);
}
說明:Object類中定義的equals()和==的作用是相同的:比較兩個物件的地址值是否相同.即兩個參考是否指向同一個物件物體,
-
像 String、Date、File、包裝類等都重寫了 Object 類中的 equals() 方法,
重寫以后,比較的不是兩個參考的地址是否相同,而是比較兩個物件的"物體內容"是否相同,
public class EqualsTest {
public static void main(String[] args) {
//參考型別:
Customer cust1 = new Customer("Tom",21);
Customer cust2 = new Customer("Tom",21);
System.out.println(cust1 == cust2);//false
String str1 = new String("xiaozhao");
String str2 = new String("xiaozhao");
System.out.println(str1 == str2); //false
System.out.println(cust1.equals(cust2)); //false(呼叫Object類中的equals()方法)
System.out.println(str1.equals(str2)); //true
Date date1 = new Date(32432525324L);
Date date2 = new Date(32432525324L);
System.out.println(date1.equals(date2)); //true
}
}
public class Customer {
public String name;
public int age;
}
18.2.3 重寫 equals() 方法
-
通常情況下,我們自定義的類如果使用equals()的話,也通常是比較兩個物件的"物體內容"是否相同,
那么,我們就需要對 Object 類中的 equals() 進行重寫,
-
重寫的原則:比較兩個物件的物體內容是否相同,
-
一般情況下,使用 IDE 自動重寫 equals() 方法,
18.3 toString() 方法
- 當我們輸出一個物件的參考時,實際上就是呼叫當前物件的 toString() 方法,
- Object類中toString()的定義:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
-
像 String、Date、File、包裝類等都重寫了 Object 類中的 toString() 方法,使得在呼叫物件的 toString() 時,回傳"物體內容"資訊,
-
自定義類也可以重寫 toString() 方法,當呼叫此方法時,回傳物件的"物體內容",
可以手動重寫和自動重寫,一般使用自動重寫,
public class ToStringTest {
public static void main(String[] args) {
Customer cust1 = new Customer("Tom",21);
System.out.println(cust1.toString()); //javase.ex.Customer@1b6d3586
System.out.println(cust1); //javase.ex.Customer@1b6d3586
String str = new String("xiaozhao");
System.out.println(str); //xiaozhao
Date date = new Date(4534534534543L);
System.out.println(date.toString()); //Mon Sep 11 08:55:34 CST 2113
}
}
public class Customer {
public String name;
public int age;
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
/*自動重寫的 toString 方法
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
*/
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/499025.html
標籤:Java
上一篇:JUnit 5簡明教程
下一篇:IDEA打包jar包詳盡流程
