第6章面向對象(下)

6.1 java 1.8 增強的包裝類

java 爲什麼要引入包裝類

1. java 是面向對象的編程語言,但它也包含了8中基本數據類型,這8中基本數據類型不支持面向對象的編程機制,基本數據類型的數據也不具備“對象”的特徵 :沒有成員變量,沒有方法可以調用  

2.只能進行簡單的,有效的常規數據處理,當所有引用都繼承了Object類,都可以當Object類使用,基本數據類型就不可以

 

自動裝箱 :就是可以吧一個基本類型的變量直接賦值給對應的包裝類變量,或者賦值給Object變量(向上自動轉型)

自動拆箱 :就是可以把包裝類對象直接賦值給一個對應的基本類型

 

包裝類還可以實現基本類型變量和字符串之間的轉換,把字符串類型轉化爲基本類型的值有兩種方法

1. 利用包裝類提供的pareXxxString s)靜態方法  (除了 Character

2. 利用包裝類提供的Xxx(String s)構造器

 

String 類提供valueOf()了將字符串轉換爲字符串

系統把 -128 ~127之間的整數自動裝箱成Integer實例,因此在這個之間的自動裝箱成了Integer實例 直接引用cache數組裏的元素

 

java 1.7爲所有的包裝類都提供了一個靜態的comparexxx val1 xxx val2) 來比較兩個類型之間值的大小 Boolean 類型 true > false

無符號位最大的特點就是最高位不在當做符號位

 

6.2 處理對象

.toString()  類名 + @ + hashCode

 

6.2.2 == equals()

java程序中測試兩個變量是否相等有兩種方法 ==運算符 和equals()

== 判斷相等

1.如果兩個變量的基本類型相同 且都是數值類型的 只要兩個變量值相等就爲true

2.對於引用類型 只有他們指向同一個類型

 

常量池 包括 類 方法 接口中產生的常量 還包括字符串常量  存在棧內存裏

 

equals()方法

1.equals() 本身是object類的一個實例方法  因此所有的引用變量都可以調用該方法來判斷變量是否相等 但是本質和 == 沒有區別

2.String重寫的equals()方法 用來判斷兩個字符串是否相等

 

6.3 類成員

同一個類的所有類變量共享都一塊內存空間

 

靜態初始化塊 在類的初始化階段,系統會調用給類的靜態初始化塊來對類進行初始化,一旦類初始化完畢之後靜態初始化塊將永遠得不到執行的機會

 

類變量不能訪問實例變量的原因是 因爲類變量的作用範圍更大,可能出現類成員已經初始化完畢了 實例變量都還不曾初始化,從而導致錯誤

 

6.3.2 單例類(Singleton

1.構造器使用private修飾

2.必須提供一個static方法來訪問

3.使用一個static修飾的成員變量來保存曾經創建的對象

 

6.4 final 修飾符

final 可以修飾類 變量 方法

修飾變量時 表示該變量一旦獲得初始值就不可以被改變,final 既可以修飾成員變量(類變量可以在定義時就指定默認值 也可以通過 靜態塊初始化 中指定;實例變量 以在定義時就指定默認值也可以通過 塊初始化和 構造器 中指定)也可以局部變量和形參

final修飾的成員變量必須由程序員顯示指定初始值 程序不會爲final成員進行初始化

 

6.4.3 final 修飾基本類型變量和引用變量的區別

final 修飾基本變量時 不能被重新賦值, 但是final 修飾引用變量時,只保證這個引用變量所引用的的地址不會發生變化,(不可以對引用變量重新賦值,但是可以改變引用對所指向象的內容)

 

6.4.4  可執行 宏替代 的final 變量

無論是 類變量 實例變量 還是局部變量 只要滿足

1. 使用final修飾

2. 在定義時就指定了 final 變量的初始值

3. 該初始值在編譯時就別確定下來

就可以相當一個直接量(編譯器會把程序中用到這個變量的地方都替換成變量的值)

關於宏變量 對於實例變量來說 只有在定義變量時指定初始值纔會 有宏變量

6.4.5 final 方法

final 修飾方法表示方法不能被重寫 (Object類裏有一個 getClass()

6.4.6 final

final 修飾類表示該類沒有子類 (java.lang.Math

6.4.7 不可變類

不可變類的意思就是 創建該類的實例後,該實例變量時不可以改變的(java8個包裝類和String類都是不可變的)

創建不可變類的原則

1. 使用private final 修飾該類的成員變量

2. 提供帶參數的構造器,根據傳入的參數來初始化該類裏的成員變量

3. 僅爲該類成員變量提供get方法 不能提供set方法

4. 有必要重寫 Object 類的 hashCode() 和equals()方法

 

不可變類的實例在整個生命週期都處於 初始化狀態

 

創建不可變類時應該注意

當創建不可變類時,如果它包含成員變量的類型是可變的,那麼其對象的成員變量就依然是可以改變的 那麼該不可變類依然是失敗的  所有要特別注意引用成員變量

6.4.8 緩存實例的不可變量

不可變類的用途

不可變類的實例狀態不可改變,可以很方便的被多個對象所共享,如果程序經常需要使用相同的不可變類,則應該緩存這種不可變類的實例 (緩存)

 

Integer類 就採用了緩存機制,如果程序執行 new構造器來創建Integer對象,則每次都是全新的對象, 如果採用 valueOf()方法在(-128 - 127)之間則採用緩存機制

 

6.5 抽象類

抽象類不能被實例化,抽象類的構造器主要是用於子類調用

 

abstract 不能修飾成員變量 局部變量和構造器

 

static 不能和abstract一起修飾方法,static abstract 可以一起修飾內部類

 

abstract修飾的方法不能用private修飾

 

 

6.6接口

java 1.8 提供了默認方法,默認方法可以提供實現方法

 

接口不能繼承類,不能有構造器和初始化塊

 

接口裏可以包含 靜態常量 方法(抽象方法 類方法 或者默認方法  ) 內部類(包括內部接口 枚舉)且 都是 public 訪問權限

 

對於接口裏的靜態常量而言 不管是否使用了public static final 修飾都是使用 public staticfinal來修飾

默認方法需要加public default 來修飾 類方法需要加 static修飾

 

因爲默認方法不能使用static修飾 所有只能在實現類中的實例來調用

 

接口類似於總綱,它制定了整個系統的總綱,它制定各模板應該遵循的標準,因此接口不應該經常改動

抽象類 類似於 中間產品 這個中間產品已經實現了系統的部分功能,但這個產品並不完整 需要進一步的完善

 

6.6.6 面向接口編程

1.簡單工廠模式:解耦合 假如某一個類需要組合另一個類 直接組合該類 或者組合一個工廠類

(1)創建一個接口(Output

(2)將這個接口做爲屬性傳入實現類中(private Output out

(3)提供一個工廠類來創建接口的對象(return new Printer())

(4)寫一個類來實現接口 (BetterPrint

(5)如果需要改變 可以將3的對象改成實現4的對象 就可以完成組合功能升級

 

2.命令模式 :某一個方法需要完成某一個行爲,這個行爲的具體實現無法確定,必須等到執行該方法時纔可以確定,所以必須傳入一個 處理行爲做參數來實現

(1)創建一個接口 定義一個處理行文的方法 (Command

(2)創建一個處理類  該類無法處理具體行爲(public void processint[] target Command cmd ))

(3)具體實現類 類中方法的參數改爲實現接口的不同類

pa.process(target , new PrintCommand());

pa.process(target, newAddCommand();

 

6.7內部類

內部類的作用

1.內部類提供了更好的封裝,可以把內部類隱藏在外部類之內,不允許包中的其他類訪問

2.內部類可以訪問外部類的私有成員

3.匿名內部類適合用於創建僅需要使用一次的類

 

內部類和外部類的區別

1.內部類比外部類可以多使用3個修飾符 private protect static

2.非靜態內部類不能用於靜態成員

 

 

6.7.1 非靜態內部類

大部分時候內部類都是定義爲成員內部類定義 (局部內部類是在方法中定義的類)

 

在外部類使用非靜態內部類和平時普通類並沒有太大區別

 

非靜態類可以直接訪問外部類private成員

因爲在非靜態內部類對象裏,保存了一個外部類對象的引用

 

當外部類 內部類 內部類的局部變量重名是 可以使用 外部類名.this this 來做區分

 

非靜態內部類的成員可以直接訪問外部類的私有成員 反之則不成立 非靜態內部類的成員只是在非靜態內部類範圍內可知的,如果外部類需要訪問非靜態類的內部類成員, 則必須顯示創建非靜態內部類的對象來調用訪問其實例變量

 

如果存在一個非靜態內部類對象時,則一定存在一個被他寄存的外部類對象,反之 則不一定成立 所以 外部類對象不能直接訪問非靜態內部類對象

 

非靜態內部類裏不能有 靜態方法 靜態成員 靜態初始化塊

 

6.7.2 靜態內部類

靜態內部類可以包含靜態成員,也可以包含非靜態成員 靜態內部類成員不能訪問外部類的實例成員 即使是靜態內部類的實例方法也不能訪問外部類的實例成員,只能訪問外部類的靜態成員

 

靜態內部類是外部類的一個靜態成員,因此外部類的所有成員都可以使用靜態內部類來定義變量,創建對象;

外部類依然不能直接訪問靜態內部類的成員,但可以通過靜態內部類作爲調用者來訪問靜態內部類的類成員,也可以使用靜態內部類對象作爲調用者來訪問靜態內部類成員

 

接口也可以定義內部類 但只能是靜態內部類

 

6.7.3 使用內部類

定義類的主要作用就是用來 定義變量 創建實例 和作爲父類被繼承,定義內部類的作用也主要是這樣 但是內部類定義和創建實例和外部類有一定的差距

1. 在外部類內部使用內部類

區別 不要在外部類的靜態成員使用非靜態內部類

2. 在外部類之外使用非靜態內部類

(1)不能使用private 修飾內部類

外部類.內部類 varName(如果外部類有包名,則加上包名)

(2)創建非靜態內部類對象時,必須先創建外部類對象

(3)在創建非靜態內部類的子類時,必須保證讓子類構造器可以調用非靜態內部類的構造器,調用非靜態內部類的構造器時,必須存在一個外部類對象

public class SubClass extends Out.In {

public SubClass(Out out) {

out.super();

因爲內部類的構造器 必須使用外部類對象來掉

 

3 在外部類之外使用靜態內部類

new外部類.內部類構造器()

 

6.7.4局部內部類

如果把一個內部類定義在方法裏,那麼這個內部類就是局部內部類,局部內部類僅在該方法體力有效,所以不能使用訪問控制符static修飾符修飾

 

6.7.5 java 8 改進的匿名內部類

匿名內部類適合創建那種只需要使用一次的類,匿名內部類必須繼承一個父類,或者實現一個接口

關於匿名內部類還有兩個規則

1.匿名內部類不能是抽象類系統創建匿名內部類時,會立即創建匿名內部類的對象

2.匿名內部類不能定義構造器,因爲匿名內部類沒有類名,所有無法定義構造器,但可以有初始化塊 所以new接口名後不能帶參數, 但如果通過繼承父類來創建匿名內部類,則將擁有和父類相似的構造器 則擁有相同的形參列表

 

java 8之前

要求被局部內部類,匿名內部類訪問的局部變量必須使用final 修飾,但是成員變量的值依然不可以改變

6.8  Lambda表達式

Lambda 表達式支持將代碼塊作爲方法參數

 

Lambda 語言結構

 

1.形參列表 形參列表允許省略形參類型,如果參數列表只有一個參數,甚至可以連參數列表的圓括號也省略

2.箭頭->

3.代碼塊

如果代碼塊只有一句語句,Lambda可以省略代碼塊的花括號,

如果lambda 語句只有一條return 語句,甚至可以省略 return

6.8.2 lambda 表達式與函數接口

Lambda表達式類型,也別稱爲 目標類型, Lambda表達式的目標類型必須是 函數式接口(函數式接口代表只包含一個抽象方法的接口,但是可以包含類方法 和默認方法)

 

Lambda表達式的結果就是被當成對象,因此程序中完全可以使用Lambda表達式進行賦值

 

Lambda 表達式有兩個侷限

1.lambda表達式的目標類型必須是函數式接口

2.lambda 表達式只能爲函數式接口創建對象, 因此只能實現一個方法,

 

爲了保證lambda表達式的目標類型必須是明確的函數式接口 有以下3中常見的方式

1. 將lambda 表示式賦值給函數式接口類型變量

2. 將lambda 表達式作爲函數接口類型的參數傳給某一個方法

3. 使用函數式接口對lambda表達式進行強制類型轉換

 

6.8.3 方法引用與構造器引用

如果lambda表達式只有一條代碼,還可以在代碼塊中使用 方法引用和構造器

需要使用2個英文冒號

 

方法引用和構造器引用可以讓Lambda表達式代碼更加簡潔

引用類方法 類名::類方法 (a,b,...->類名.方法名(a,b,...)

引用特定對象的實例 特定對象::實例方法 (a,b,...)->特定對象.實例方法(a,b,...

引用某類對象的實例方法  類名::實例方法 (a,b,...)-> a.實例方法(b,...)

引用構造器  類名::new   (a,b,...) ->new 類名(a,b,...a

 

6.8.4 Lambda表達式和匿名內部類的聯繫和區別

相同點

Lambda 表達式與內部類一樣 都可以直接訪問 effectively final 的局部變量 以及外部類的成員變量

Lambda表達式創建對象和匿名類創建對象一樣 都可以直接調用從接口中繼承的默認方法

 

區別

1. 匿名內部類可以爲任意接口創建實例

2. 匿名內部類可以爲抽象類甚至是普通類創建實例

3. 匿名內部類實現的抽象方法的方法體允許調用接口中定義的默認方法,lambda表達式不允許調用默認方法

 

6.9 枚舉類

在某些情況下一個類的對象固定而且有限,在java裏被稱爲枚舉類

java5新增了一個enum 關鍵字用來定義枚舉類

 

6.9.1枚舉類入門

枚舉類和普通類的區別

1.枚舉類默認繼承java.lang.Enum類,因此不能顯示繼承其他父類

2.使用enum定義、非抽象枚舉默認都會使用final修飾 因此不能有子類

3.枚舉類的構造器只能使用private訪問修飾符

4.枚舉類的實例都必須在枚舉類的第一行顯示列出

 

枚舉類提供了一個values()方法可以遍歷出所有的枚舉值

 

6.9.3枚舉類的成員變量、方法和構造器

當創建MALE這樣的枚舉值並不是直接創建枚舉類的實例 而是相當於創建了枚舉類的匿名子類的實例

 

抽象枚舉類使用的是abstract 而並非final

 

6.10 對象與垃圾回收機制

垃圾回收機制的特點

1.垃圾回收機制只能回收堆內存的對象,不會回收任何物理資源

2.程序無法精確的控制垃圾回收機制的運行,只會在合適的時候進行

3.在垃圾回收機制回收任何對象之前,總會先調用它的finalize()方法,該方法有可能使該對象重新復活

 

6.10.1 對象在內存中的狀態

根據引用的狀態 可分爲三個狀態 可達狀態(有引用變量引用它) 可恢復狀態(不在有引用指向) 不可達狀態(引用被切斷 卻調用了finalize()方法 認沒有達到可達狀態)

 

當某一個對象被其他類變量引用,只有該類被銷燬後,該對象纔可以變成可恢復狀態

當某一個對象被其他對象的實例變量引用 只有當該對象被銷燬後,纔會變成可恢復狀態

 

6.10.2 強制垃圾回收

垃圾回收時間總是不確定的 但是程序強制系統垃圾回收總是有些效果的

System.gc();

Runtime.getRuntime().gc();

6.10.3 fianlize方法

finalize java提供的默認機制來清理該對象的資源,該方法是定義在Object類裏的實例方法 當方法返回後,對象消失,垃圾回收機制執行

fianlize()方法4個特點

1. 永遠不要主動調用某一個對象的finalize()方法,應該交給垃圾回收機制調用

2. finalize()調用時間具有不確定性

3. 當jvm執行finalize()方法時,該對象可能會達到可達狀態

4. 當jvm執行finalize()方法異常時,垃圾回收機制不會報告異常,而是繼續執行

 

6.10.4 對象的軟 弱和虛引用

1.強引用 java最常見的引用方式 ,程序創建一個對象,並把這個對象賦給一個引用變量,

程序通過這個引用變量來操作實際的對象(處於可達狀態)

 

2.軟引用 軟引用通過SoftReference 類來實現 當一個類只有軟引用時,它可能被GC回收 當系統內存不足時,系統可能就會回收它。(用於對內存敏感的程序中)

 

3.弱引用 通過WeakReference 類實現 當GC運行時,無論內存足不足都沒被回收對象所佔的內存

 

4.虛引用 通過實現PhantomReference 類實現,虛引用完全類似於沒有引用,虛引用本身對對象沒有太大影響  主要用於跟蹤對象被垃圾回收的狀態 虛引用不能單獨存在,必須和引用隊列一起存在

上面3個引用都包含了一個get()方法,用於獲取被它們所引用的對象

 

引用隊列 是用於保存被回收的對象的引用,使得對象在回收之前還可以採取行動

軟引用和弱引用可以單獨使用 ,但虛引用不能 主要用於跟蹤對象被GC回收狀態, 和檢查引用隊列是否包含 從而瞭解虛引用對象是否將被回收

 

 

6.11 修飾符的使用範圍

strictfp 關鍵字的含義是 FP-strict(精確浮點) 用於外部類 接口 方法 和成員內部類

native 用來修飾方法  如果某一個方法需要利用平臺相關特性,或者訪問硬件等,就可以採用native 修飾的方法,再把該方法叫給C去實現  但是一旦使用了native 就失去了跨平臺的功能

 

abstractfinal 不能同時使用

abstractstatic 不能同時修飾方法 可以同時修飾內部類

abstract private 不能同時修飾方法 可以同時修飾內部類

private final可以同時修飾方法 但是沒有意義

 

6.12 使用jar文件

自帶的 META-INF/MANIFEST.MF的清單文件

jar 優點

1.安全 能夠對JAR文件進行數字簽名

2.加快下載速度

3.壓縮

4.包封裝

5.可移植

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章