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)

1566424782835

6.包裝類的使用

1566424884812

裝箱:基本數據類型--->包裝類

拆箱:包裝類--->基本數據類型

//裝箱  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修飾的程式碼塊

  1. 可以有輸出語句。
  2. 可以對類的屬性、類的聲明進行初始化操作。
  3. 不可以對非靜態的屬性初始化。即:不可以調用非靜態的屬性和方法。
  4. 若有多個靜態的程式碼塊,那麼按照從上到下的順序依次執行。
  5. 靜態程式碼塊的執行要先於非靜態程式碼塊。
  6. 靜態程式碼塊隨著類的載入而載入,且只執行一次。

非靜態程式碼塊:沒有static修飾的程式碼塊

  1. 可以有輸出語句。
  2. 可以對類的屬性、類的聲明進行初始化操作。
  3. 除了調用非靜態的結構外,還可以調用靜態的變數或方法。
  4. 若有多個非靜態的程式碼塊,那麼按照從上到下的順序依次執行。
  5. 每次創建對象的時候,都會執行一次。且先於構造器執行。

9.抽象類和抽象方法

  • 用abstract關鍵字來修飾一個類,這個類叫做抽象類。
  • 用abstract來修飾一個方法,該方法叫做抽象方法。

10.interface

  • 用interface來定義。
  • 介面中的所有成員變數都默認是由public static final修飾的。
  • 介面中的所有抽象方法都默認是由public abstract修飾的。
  • 介面中沒有構造器。
  • 介面採用多繼承機制。

定義Java類的語法格式:先寫extends,後寫implements

class SubClass extends SuperClass implements InterfaceA{ }


介面和抽象類之間的對比

1566430499232

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後面的異常類型可 以是方法中產生的異常類型,也可以是它的父類。
  • 重寫方法不能拋出比被重寫方法範圍更大的異常類型。

Tags: