1. 類、超類、子類
1.1 定義子類
- 關(guān)鍵字extends表明正在構(gòu)造的新類派生于一個已存在的類。
- 已存在的類稱為超類、基類或父類。
- 新類稱為子類、派生類或孩子類。
1.2 覆蓋(override)方法
- 在子類中可以增加域、增加方法或者覆蓋超類的方法,絕對不能刪除繼承的任何域和方法
1.3 子類構(gòu)造器
- 如果子類的構(gòu)造器沒有顯式地調(diào)用超類的構(gòu)造器,則自動調(diào)用超類默認(沒有參數(shù))的構(gòu)造器
- 如果超類沒有不帶參數(shù)的構(gòu)造器,并且在子類的構(gòu)造器中又沒有顯式地調(diào)用超類的其他構(gòu)造器,則Java編譯器將報告錯誤。
1.4 繼承層次
- 繼承并不僅限于一個層次,由一個公共超類派生出來的所有類的集合被稱為繼承層次
- 在繼承層次中,從某個特定的類到祖先的路徑被稱為該類的繼承鏈
- 通常,一個祖先類可以擁有多個子孫繼承鏈
- Java不支持多繼承
1.5 多態(tài)
- "is-a"規(guī)則用來判斷是否應(yīng)該設(shè)計為繼承關(guān)系的簡單規(guī)則,它表明子類的每個對象也是超類的對象,另一種表述法是置換法則
1.6 理解方法調(diào)用
- 調(diào)用過程:
1) 編譯器查看對象的聲明類型和方法名
2) 編譯器查看調(diào)用方法時提供的參數(shù)類型
3) 如果是private方法、static方法、final方法或者構(gòu)造器,那么編譯器將可以準確地知道應(yīng)該調(diào)用哪個方法,這種調(diào)用方式稱為靜態(tài)綁定
4) 當(dāng)程序運行,并且采用動態(tài)綁定調(diào)用方法時,虛擬機一定調(diào)用與x所引用的實際對象類型所最適合的那個類的方法
1.7 阻止繼承:final類和方法
- 不允許擴展的類被稱為final類,如果在定義類的時候使用了final修飾符就表明這個類是final類。
- 類中的特定方法也可以被聲明為final,聲明后,子類就不能覆蓋這個方法(final類中的所有方法自動成為final方法)
- 域也可以聲明為final,但聲明后就不能修改他們的值了,如果將一個類聲明為final,只有其中的方法自動地成為final,而不包括域
1.8 強制類型轉(zhuǎn)換
- 將一個類型強制轉(zhuǎn)換成另外一個類型的過程被稱為類型轉(zhuǎn)換
- 只能在繼承層次內(nèi)進行類型轉(zhuǎn)換
- 在將超類轉(zhuǎn)換為子類之前,應(yīng)該使用instanceof進行檢查
1.9抽象類
- 抽象類中包含一個或多個抽象方法的類本身必須聲明為抽象的。
public abstract class Person
{
...
public abstract String getDescription();
}
除了抽象方法之外,抽象類還可以包含具體數(shù)據(jù)和具體方法。
抽象方法充當(dāng)著占位的角色,它們的具體實現(xiàn)在子類中。擴展抽象類可以有兩種選擇:</br>
一種是在抽象類中定義部分抽象類方法或不定義抽象類方法,這樣就必須將子類也標記為抽象類;
另一種是定義全部的抽象方法。類即使不含抽象方法,也可以將類聲明為抽象類。
抽象類不能被實例化。 如果將一個類聲明為abstract,就不能創(chuàng)建這個類的對象。
如:
new Person("VInce");
但是可以創(chuàng)建一個具體子類的對象
如:
Person p = new Student("Vince","Economics");
注意:可以定義一個抽象類的變量,當(dāng)時只能引用非抽象子類的對象
受保護訪問
- Java用于控制可見性的四個訪問控制符:
1) 對所有類可見 ——————— public
2) 對本包和所有子類可見———— protected
3) 對本包可見 ———————— 默認,不需要修飾符
4) 僅對本類可見 ——————— private
2. Object:所有類的超類
- Object是Java中所有類的始祖,在java中每個類都是由它擴展而來的。
但是不用這么寫:
public class Employee extends Objcet
- 如果沒有明確指定出超類,Object就會被認為是這個類的超類。
- 可以使用Object類型的變量引用任何類型的對象:
Objcet obj = new Employee("Hacker",35000);
2.1 equals方法
- Object類中的equals方法用于檢測一個對象是否等于另一個對象。
String str1=new String("apple");
String str2=new String("apple");
System.out.println(str1.equals(str2)); //true
- 與 == 的差別
String str1=new String("apple");
String str2=new String("apple");
System.out.println(str1.equals(str2)); //true
System.out.println(str1 == str2); //false
在檢測中,只有兩個對象屬于同一個類時,才有可能相等。
2.2 相等測試與繼承
- 當(dāng)隱式和顯式參數(shù)不屬于同一個類時,即要比較的對象不是同屬一個類時,equals方法返回false。
許多程序員喜歡使用instanceof進行檢測:
if(!(otherObjcet instanceof Employee)){
return flase;
}
- java要求equals具有下列特性:
1) 自反性:對于任何非空引用x,x.equals(x)應(yīng)該返回true;
2) 對稱性:對于任何引用x和y,當(dāng)且僅當(dāng)y.equals(x)返回true時,x.equals(y)也應(yīng)該返回true;
3) 傳遞性:對于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也應(yīng)該返回true;
4) 一致性:如果x和y引用的對象沒有發(fā)生變化,反復(fù)調(diào)用x.equals(y)應(yīng)該返回同樣的結(jié)果。
</br> 5) 對于任何非空引用x,x.equals(null)應(yīng)該返回false。
2.3 hashcode方法
- hashcode(散列碼)是由對象導(dǎo)出的一個整形值
- 如果x、y是不同的對象,x.hashCode()和y.hashCode()基本不會相同
- StringBuffer中沒有定義hashCode方法,它的散列碼是由Object類默認的hashcode方法導(dǎo)出的對象儲存地址
- 如果重新定義equals方法,就必須重新定義hashCode方法
- Equals與hashCode的定義必須一致:如果x.equals(y)返回true,則x.hashCode()就必須與y.hashCode()具有相同的值。
2.4 toString方法
- toStirng方法用于返回表示對象值的字符串
- 絕大多數(shù)(但不是全部)的toString方法都遵循這樣的格式:類的名字,隨后是一對方括號括起來的值
public String toString()
{
return "className[.......]";
}
或者
... toString()
{
return getClass().getName()+"[......]"
}
- 設(shè)計子類時也應(yīng)該定義自己的toString方法,并將子類的描述添加進去。如果使用了getClass().getName(),那么子類只要調(diào)用super.toString()就好了。
3. 泛型數(shù)組列表
- ArrayList是一個采用類型參數(shù)(type parameter)的泛型類。
- 為了指定數(shù)組列表保存的元素對象類型,需要用一對尖括號將類名包括起來加在后面:ArrayList<className>
ArrayList<Employee> staff = new ArrayList<>();
- 使用add方法可以將元素添加到數(shù)組列表中
staff.add(new A("abc",...));
staff.add(new A("cdf",...));
- size方法將返回數(shù)組列表中包含的實際元素數(shù)目:staff.size() ,將返回staff數(shù)組列表的的大小,等價于a的a.length()。
3.1訪問數(shù)組列表元素
- 使用get和set方法實現(xiàn)訪問或者改變數(shù)組元素的操作
staff.set(i,harry);
等價于
a[i] = harry;
get方法同理
- 沒有泛型時,原始的ArrayList類提供的get方法只能返回Object,因此,調(diào)用get方法必須對返回值進行類型轉(zhuǎn)換。
Employee e = (Employee) staff.get(i);
4 對象包裝器與自動裝箱
-
所有的基本類型都有一個與之相對應(yīng)的類。
如Integer類對應(yīng)基本類型int。 - 包裝類:Integerl、Long、Float、Double、Short、Byte、Character、Void和Boolean。對象包裝類時不可變的。
- 對象包裝類還是final,因此不能定義他們的子類。
- 先聲明一個Integer對象的數(shù)組列表
ArrayList<Integer> list = new ArrayList<>();
當(dāng)調(diào)用list.add(3)時會自動變換成list.add(Integer.valueOf(3));
這種變換就叫做自動裝箱(autoboxing)
當(dāng)調(diào)用list.get(i)時會變換成list.get(i).intValue()
未完待補充