1. 程式人生 > >五、面向物件(下)

五、面向物件(下)

1、JAVA增強的包裝類

JAVA為8種資料型別定義了相應的引用型別,並稱之為基本資料型別的包裝類。
(1)自動裝箱與自動拆箱
自動裝箱就是把一個基本型別變數自動賦值給對應的包裝類變數,或者賦值給Object變數;自動拆箱就是將包裝類物件直接賦值給一個對應的基本型別變數。
(2)包裝類提供了一些方法用於實現基本型別變數和字串之間的轉換
利用包裝類提供的parseXxx(String str);靜態方法(Character類沒有提供該方法)
利用包裝類提供的Xxx(String str);構造器
String類也同樣提供了多個過載valueOf();方法,用於將基本型別變數轉換成字串。
(3)包裝類的比較
包裝類和基本型別之間的比較:將兩個變數直接進行相比。

Integer a = new Integer();
//輸出true
System.out.println("" + (a > 0.5));

包裝類與包裝類之間的比較:只有兩個包裝類的例項指向同一個物件的時候才會相等。

Integer a = 2;
Integer b = 2;
System.out.println("" +  (a == b));//返回TRUE
Integer a = 128;
Integer b = 128;
System.out.println("" +  (a == b));//返回FALSE

上面的結論沒錯!程式也沒錯!在這裡系統將-128~127之間的整數放在了cache的陣列中快取了起來,所以一開始的a和b是指向的同一個物件。而當超過127之後,系統就會重新建立物件,所以後面的a和b就不相等了。

2、處理物件

(1)toString方法
Object類提供的toString方法會返回“類名 + @ + hashcode”值。由於每個類都會直接或者間接繼承Object這個類,如果使用者不滿足Object類中toString方法的返回結果,就應該重寫這個方法,來達到自己滿意的結果。
(2)==和equals
一般情況下,利用 " == "比較兩個引用變數,除非它們指向同一個物件,才會返回TRUE。並且 == 不可用於比較型別上沒有父子關係的兩個物件。equals方法也是Object的方法,它的功能跟 == 沒什麼區別,因此我們應當重寫equals這個方法,來達到我們預期的目的。

3、final修飾符

(1)什麼是final修飾符?
final用於表示它所修飾的類、方法和變數不可改變。
(2)final修飾變數
<1>因為一旦經過final進行過修飾便不能被改變。因此對於成員變數來說賦初值要遵循以下原則。
類變數:必須在靜態初始化快中指定初始值或者宣告該類變數時指定初始值
例項變數:必須在非靜態初始化塊、宣告該變數例項或者構造器中指定初始值
<2>final也可以修飾區域性變數,當定義final區域性變數的時候沒有賦初始值,那麼可以在接下來對進行一次賦值,只能一次。如果在定義的時候已經指定了的話,那麼在以後就不可以再對該變數賦值。
(3)final修飾方法
final修飾的方法不可以被重寫,但是依然可以被過載。
(4)final修飾類
final修飾的類不可以有子類。
(5)不可變類
不可變類指的是建立該類的例項之後,該例項的例項變數是不可改變的。

4、抽象類

(1)什麼是抽象類?
有抽象方法的類或者使用abstract修飾符修飾的類。
(2)抽象方法和抽象類的定義規則
<1>抽象類和抽象方法必須使用abstract修飾符來修飾。抽象方法不能有方法體。
<2>抽象類不能被例項化。
<3>含有抽象方法的類只能被定義成抽象類。
注:abstract不能用於修飾區域性變數,也就是說沒有抽象變數,抽象成員變數的說法。也不能用於修飾構造器。
如果用static修飾方法,那麼這個方法是類方法,可以被呼叫。但如果同時加上abstract來進行修飾,則會導致呼叫該方法時發生衝突,因此兩個修飾符不能同時使用。
子類中含有沒有重寫的abstract方法,那麼子類依然是一個抽象類。因此abstract不能和private同時使用。

5、介面

(1)什麼是介面?
特殊的抽象類,是多個類共同的公共行為規範。
(2)介面的定義

[修飾符] interface 介面名 extends 父介面1, 父介面2...
{
	//常量定義
	.....
	//抽象方法定義
	.....
	//內部類、介面、列舉定義...
	.....
	//預設方法或者類方法定義
	......
}

注:介面的成員變數只能是靜態常量,因此在定義成員變數的時候不管是否使用public static final修飾符來修飾,介面的成員變數總是使用這三個修飾符來修飾。介面的方法只能是抽象方法、類方法、或者預設方法,抽象方法預設使用abstract來修飾,預設方法必須使用default來修飾,由介面實現類的例項來呼叫這些預設方法,類方法必須使用static來修飾,可以直接使用介面來呼叫。
(3)介面的繼承
介面支援多繼承。即一個介面可以有多個直接父介面。子介面會獲得父接口裡定義的所有抽象方法和常量。
(4)介面的用途
定義變數:用於進行強制型別轉換,即為介面變數賦值的時候必須使用其實現類的物件。也就是說,哪個類實現了這個介面,那麼這個類的物件就可以為這個介面的變數賦值。
呼叫介面中定義的常量
被其他類實現:一旦類實現了一個或者多個介面,那麼這個類必須實現這些接口裡定義的全部抽象方法,否則該類會成為抽象類。

6、內部類

1、內部類的定義和作用。
定義:把一個類放在另一個類的內部進行定義。
作用:<1>、可以實現更好的封裝,不允許同一個包中的其他類訪問該類。
<2>、內部類可以訪問外部類的私有資料,但外部類不可以訪問內部類成員。
<3>、匿名內部類僅適合建立那些僅需要一次使用的類。
<4>、內部類可以多使用private,protected,static修飾符。
<5>、非靜態內部類不可以擁有靜態成員。
2、非靜態內部類
沒有使用static修飾的內部類是非靜態內部類。
不論是外部類的類成員變數,還是例項成員變數都不能訪問非靜態內部類的成員。
3、靜態內部類
使用static修飾的內部類是靜態內部類。
靜態內部類不能訪問外部類的例項成員,只能訪問外部類的類成員。
外部類依然不能直接訪問靜態內部類的成員,但可以用靜態內部類的類名作為呼叫者來訪問靜態內部類的類成員,使用靜態內部類的類物件來訪問靜態內部類的例項成員。
介面中也可以定義內部類,但接口裡定義的內部類預設使用public static修飾,即介面內部類只能是靜態內部類。
4、使用內部類
<1>在外部類以外的地方定義內部類,語法格式:

Outerclass.Innerclass varName = new Outerclass.Innerclass();//靜態內部類
Outerclass.Innerclass varName = new Outerclass().new Innerclass();//非靜態內部類

5、匿名內部類
<1>匿名內部類的特點
建立匿名內部類的時候會立即創建出一個該類的物件,這個類定義立即消失,匿名內部類不能重複使用。
<2>語法格式

new 實現介面() | 父類構造器(實參列表)
{
	//匿名內部類的類體
}

<3>匿名內部類的規則
匿名內部類必須繼承一個父類或者實現一個介面,但最多隻能繼承一個父類或者實現一個介面;
匿名內部類不能是抽象類,也就是說必須將父類或者介面中的抽象方法全部實現;
匿名內部類不能定義構造器,因為匿名內部類沒有類名,所以無法定義構造器,但匿名內部類可以定義初始化塊,通過初始化塊來完成構造器需要完成的事情;
匿名內部類的使用的區域性變數是一個final變數。

7、Lambda表示式

<1>組成部分
形參列表:形參列表允許省略形參型別。如果形參列表中只有一個引數,甚至連形參列表的圓括號也可以省略;
箭頭(->);
程式碼塊:如果程式碼塊中只包含一條語句,那麼可以省略花括號;Lambda程式碼塊中只有一條return語句,可以省略return關鍵字。

fun(array, (int[] target)->{
	System.out.println("哈哈!");//可以省略花括號
});

<2>Lambda表示式使用要求
必須是函式式介面,也就是說該介面只能有一個抽象方法。Lambda只能為函式式介面建立物件。
<3>Lambda表示式的用途
將Lambda表示式賦值給函式式介面型別的變數;
將Lambda表示式作為函式式介面型別的引數傳給某個方法;
使用函式式介面對Lambda表示式進行強制轉換。

//最後一個用途示例
//按理說Object不是函式式介面,但可以通過強轉進行賦值
Object obj = (Runnable)()->3;

<4>方法引用和構造器引用
如果Lambda表示式只有一句程式碼,那麼可以在程式碼塊中使用方法和構造器引用。

種類 示例 Lambda表示式
引用類方法 類名::類方法 (a,b,…)->類名.類方法(a,b,…)
引用特定物件的例項方法 特定物件::例項方法 (a,b,…)->特定物件.例項方法(a,b,…)
引用某類物件的例項方法 類名::例項方法 (a,b,…)->a.例項方法(a,b,…)
引用構造器 類名::new (a,b,…)->new 類名(a,b,…)

8、列舉類

<1>列舉類與普通類的區別
列舉類可以實現一個或者多個介面,使用enum定義的列舉類預設繼承了java.lang.Enum類,而不是Object類,因此列舉類不能顯式繼承其他父類;
非抽象的列舉類預設使用final修飾,因此列舉類不可派生出子類;
列舉類的構造器只能使用private訪問控制符;
列舉類的所有例項必須在列舉類的第一行顯式列出,否則列舉類永遠不能產生例項。列舉類的例項系統預設自動新增public static final修飾符。
<2>實現介面的列舉類
如果需要每個列舉值在呼叫該方法的時候呈現出不同的行為方式,則可以讓每個列舉值分別實現該方法,每個列舉值提供不同的實現方法。
<3>包含抽象方法的列舉類
列舉類中定義抽象方法時不能使用abstract關鍵字將列舉類定義成抽象類,系統會自動新增,但因為列舉類需要顯式建立列舉值,而不是作為父類,所以定義每個列舉值時必須為抽象方法提供實現,否則將出現編譯錯誤。