1. 程式人生 > >Java面向物件特性總結

Java面向物件特性總結

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

  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{ }


介面和抽象類之間的對比

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