Java面向對象特性總結
- 2019 年 10 月 3 日
- 筆記
1.面對對象與面對過程的區別
什麼是封裝?我看到過這樣一個例子:
我要用洗衣機洗衣服,只需要按一下開關和洗滌模式就可以了。有必要了解洗衣機內 部的結構嗎?有必要碰電動機嗎?有必要了解如何通電的嗎?
如果是對於面向過程來說,這些你都得知道。「吾生也有涯,而知也無涯」,面向對象的封裝與莊子的思想遙相呼應:用有限的時間去做更適合的事情。
面對過程是軟體開發的先驅者,但其局限性不能滿足當今的主流市場需求。
面對過程注重微觀,每一步都親力親為;面對對象注重宏觀,更加偏向於整體的流程。
性能:面對過程執行效率更高。Java是編譯成位元組碼給JVM運行,而面向過程直接編譯成機器碼執行
復用性:面對對象的封裝,繼承極大的擴展了程式碼的復用性
2.面對對象特徵——封裝
封裝的核心思想是隱藏實現,暴露介面。
封裝的目的:
- 解耦(符合迪米特法則)
- 保護數據安全(通過getter方法來獲取類中屬性值)
- 訪問許可權修飾符
修飾符 | 許可權範圍
public | 本類,子類,本包,外部包
protected | 本類,子類,本包
default | 本類,子類
private | 本類
3.面對對象特徵——繼承
繼承主要目的是實現程式碼復用。
特性:
- 子類具有父類非private的屬性和方法
- 子類可以擴展自己的屬性和方法
構造器的繼承問題
- 構造器是不會被子類繼承的,但子類的對象在初始化時會默認調用父類的無參構造器。
- 當父類顯示寫了有參構造器,且沒有無參構造器。子類繼承父類的時候必須顯示的調用父類的有參構造器。調用的方式可以使用super(a,b)來調用。
static修飾符的繼承問題
子類是不會繼承父類被static修飾的方法和變數,但是可以調用。
super 與 this 關鍵字
super關鍵字:我們可以通過super關鍵字來實現對父類成員的訪問,用來引用當前對象的父類。
this關鍵字:指向自己的引用。
final關鍵字
final 關鍵字聲明類可以把類定義為不能繼承的,即最終類;或者用於修飾方法,該方法不能被子類重寫:
- 方法不能重寫
- 類不能繼承
- final標記的變數(成員變數或局部變數)即稱為常量。名稱大寫,且只 能被賦值一次。
子類對象實例化過程
new出一個子類對象的時候,必須先new出一個父類對象。子類在調用構造方法時,會先調用父類的構造方法。(默認)
如果不寫構造方法,編譯器默認加上一個無參構造器。如果寫了構造器,編譯器不會添加。
如果寫了有參構造器,子類就必須調用父類的構造方法。super(參數)。
如果同時有有參和無參構造器,那麼會默認調用無參。也可以自定義調用有參。
4.面對對象特徵——多態
提高了程式碼的通用性。
多態分為編譯時多態(方法重載)和運行時多態(方法重寫)。
- 重載與重寫
重寫指子類重寫父類的方法,方法名、參數列表必須相同,返回值範圍小於等於父類,拋出的異常範圍小於等於父類,訪問修飾符範圍大於等於父類;如果父類方法訪問修飾符為 private或者final 則子類就不能重寫該方法。
重載發生在同一個類中,方法名必須相同,參數類型不同、個數不同、順序不同,方法返回值和訪問修飾符可以不同。
- 向上轉型
在多態中需要將子類的引用賦給父類對象,只有這樣該引用才既能可以調用父類的方法,又能調用子類的方法。
強制轉換
從子類到父類的類型轉換可以自動進行
從父類到子類的類型轉換必須通過造型(強制類型轉換)實現
無繼承關係的引用類型間的轉換是非法的
5.Object類
- Object類是所有Java類的根父類
- 如果在類的聲明中未使用extends關鍵字指明其父類,則默認父類 為java.lang.Object類(任何類都可以調用Object的方法)
package java.lang; public class Object { private static native void registerNatives(); static { registerNatives(); } public final native Class<?> getClass(); public native int hashCode(); public boolean equals(Object obj) { return (this == obj); } protected native Object clone() throws CloneNotSupportedException; public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } public final native void notify(); public final native void notifyAll(); public final native void wait(long timeout) throws InterruptedException; public final void wait(long timeout, int nanos) throws InterruptedException { if (timeout < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos > 0) { timeout++; } wait(timeout); } public final void wait() throws InterruptedException { wait(0); } protected void finalize() throws Throwable { } } Object的主要組成:
- public native int hashCode(); 取得hash碼
- equals(Object obj) 比較對象
- clone() 可用於複雜對象的深拷貝
==與equals的區別
== 既可以比較基本類型也可以比較引用類型。對於基本類型就是比較值,對於引用類型 就是比較記憶體地址。
equals的話,,如果該方法沒有被重寫過默認等同於==;
但是很多類默認重寫了:(比如String)

6.包裝類的使用

裝箱:基本數據類型--->包裝類
拆箱:包裝類--->基本數據類型
//裝箱 Integer t = new Integer(500); //float to Float Float f = new Float(「4.56」); //拆箱 Integer x = 3; int i = x.intValue(); //int to String String str = String.valueOf(1); //String to int int x = Integer.parseInt(str1) ; //包裝類 to String Integer x = 8; String str = x.toString(); or String str = Integer.toString(3); 7.static關鍵字
在Java類中,可用static修飾屬性、方法、程式碼塊、內部類。
被修飾後的成員具備以下特點:
- 修飾的成員,被所有對象所共享
- 訪問許可權允許時,可不創建對象,直接用類名.屬性或方法調用
在static方法內部只能訪問類的static修飾的屬性或方法,不能訪問類的非static的結構。
static修飾的方法不能被重寫
static的應用:單例模式——靜態內部類
class StaticClassInner { private StaticClassInner() {} /* 使用靜態內部類,實現了延遲載入 調用getInstance()方法時,才會載入StaticClassInnerInstance。 通過JVM類載入執行緒安全的機制,避免了執行緒不安全。 */ private static class StaticClassInnerInstance { private static final StaticClassInner INSTANCE = new StaticClassInner(); } public static StaticClassInner getInstance() { return StaticClassInnerInstance.INSTANCE; } } public class Operation { public static void main(String[] args) { StaticClassInner doubleCheck1 = StaticClassInner.getInstance(); StaticClassInner doubleCheck2 = StaticClassInner.getInstance(); System.out.println(doubleCheck1.hashCode()); System.out.println(doubleCheck2.hashCode()); } } 8.程式碼塊
對類或對象進行初始化。
程式碼塊可分為靜態程式碼塊和非靜態程式碼塊。(有無static修飾)
靜態程式碼塊:用static修飾的程式碼塊
- 可以有輸出語句。
- 可以對類的屬性、類的聲明進行初始化操作。
- 不可以對非靜態的屬性初始化。即:不可以調用非靜態的屬性和方法。
- 若有多個靜態的程式碼塊,那麼按照從上到下的順序依次執行。
- 靜態程式碼塊的執行要先於非靜態程式碼塊。
- 靜態程式碼塊隨著類的載入而載入,且只執行一次。
非靜態程式碼塊:沒有static修飾的程式碼塊
- 可以有輸出語句。
- 可以對類的屬性、類的聲明進行初始化操作。
- 除了調用非靜態的結構外,還可以調用靜態的變數或方法。
- 若有多個非靜態的程式碼塊,那麼按照從上到下的順序依次執行。
- 每次創建對象的時候,都會執行一次。且先於構造器執行。
9.抽象類和抽象方法
- 用abstract關鍵字來修飾一個類,這個類叫做抽象類。
- 用abstract來修飾一個方法,該方法叫做抽象方法。
10.interface
- 用interface來定義。
- 介面中的所有成員變數都默認是由public static final修飾的。
- 介面中的所有抽象方法都默認是由public abstract修飾的。
- 介面中沒有構造器。
- 介面採用多繼承機制。
定義Java類的語法格式:先寫extends,後寫implements
class SubClass extends SuperClass implements InterfaceA{ }
介面和抽象類之間的對比

11.內部類
在Java中,允許一個類的定義位於另一個類的內部,前者稱為內部類,後者 稱為外部類。
Inner class的名字不能與包含它的外部類類名相同;
成員內部類(static成員內部類和非static成員內部類)
class Outer { private int s; public class Inner { public void mb() { s = 100; System.out.println("在內部類Inner中s=" + s); } } public void ma() { Inner i = new Inner(); i.mb(); } } public class InnerTest { public static void main(String args[]) { Outer o = new Outer(); o.ma(); } } 局部內部類(不談修飾符)
class 外部類{ 方法(){ class 局部內部類{ } } {class 局部內部類 { } } } - 只能在聲明它的方法或程式碼塊中使用,而且是先聲明後使用。除此之外的任何地方 都不能使用該類
- 但是它的對象可以通過外部方法的返回值返回使用,返回值類型只能是局部內部類 的父類或父介面類型
- 局部內部類可以使用外部方法的局部變數,但是必須是final的。
匿名內部類
匿名內部類不能定義任何靜態成員、方法和類,只能創建匿名內部類的一 個實例。一個匿名內部類一定是在new的後面,用其隱含實現一個介面或 實現一個類。
匿名內部類的特點
- 匿名內部類必須繼承父類或實現介面
- 匿名內部類只能有一個對象
- 匿名內部類對象只能使用多態形式引用
interface A{ public abstract void fun1(); } public class Outer{ public static void main(String[] args) { new Outer().callInner(new A(){ //介面是不能new但此處比較特殊是子類對象實現介面,只不過沒有為對象取名 public void fun1() { System.out.println(「implement for fun1"); } });// 兩步寫成一步了 } public void callInner(A a) { a.fun1(); } } 12.異常處理
異常:在Java語言中,將程式執行中發生的不正常情況稱為「異常」。
(開發過程中的語法錯誤和邏輯錯誤不是異常)
Java程式在執行過程中所發生的異常事件可分為兩類:
- Error:Java虛擬機無法解決的嚴重問題。如:JVM系統內部錯誤、資源 耗盡等嚴重情況。一般不編寫針對性 的程式碼進行處理。
- Exception: 其它因編程錯誤或偶然的外在因素導致的一般性問題,可以使 用針對性的程式碼進行處理。
異常處理機制一: try-catch-finally
在編寫程式時,經常要在可能出現錯誤的地方加上檢測的程式碼, 如進行x/y運算時,要檢測分母為0,數據為空,輸入的不是數據 而是字元等。過多的if-else分支會導致程式的程式碼加長、臃腫, 可讀性差。因此採用異常處理機制。
Java程式的執行過程中如出現異常,會生成一個異常類對象, 該異常對象將被提交給Java運行時系統,這個過程稱為拋出 (throw)異常。
如果一個方法內拋出異常,該異常對象會被拋給調用者方法中處 理。如果異常沒有在調用者方法中處理,它繼續被拋給這個調用 方法的上層方法。這個過程將一直繼續下去,直到異常被處理。 這一過程稱為捕(catch)異常。
程式設計師通常只能處理Exception,而對Error無能為力。
異常處理是通過try-catch-finally語句實現的。
try{
...... //可能產生異常的程式碼
}
catch( ExceptionName1 e ){
...... //當產生ExceptionName1型異常時的處置措施
}
catch( ExceptionName2 e ){
...... //當產生ExceptionName2型異常時的處置措施
}
[ finally{
...... //無論是否發生異常,都無條件執行的語句
} ]
如果拋出的異常是IOException等類型的非運行時異常,則必須捕獲,否則 編譯錯誤。也就是說,我們必須處理編譯時異常,將異常進行捕捉,轉化為 運行時異常。
異常處理機制二: throws
- 如果一個方法(中的語句執行時)可能生成某種異常,但是並不能確定如何處理這 種異常,則此方法應顯示地聲明拋出異常,表明該方法將不對這些異常進行處理, 而由該方法的調用者負責處理。
- 在方法聲明中用throws語句可以聲明拋出異常的列表,throws後面的異常類型可 以是方法中產生的異常類型,也可以是它的父類。
- 重寫方法不能拋出比被重寫方法範圍更大的異常類型。