1. 程式人生 > >Java核心技術 卷I 基礎知識 學習筆記(6)

Java核心技術 卷I 基礎知識 學習筆記(6)

參考:Java核心技術 卷I 基礎知識

介面,主要用來描述類具有什麼功能,而並不給出每個功能的具體實現。一個類可以實現一個或多個介面,並在需要介面的地方,隨時使用實現了相應介面的物件。介面不是類,是對類的一組需求描述,這些類要遵從介面描述的統一格式進行定義。

介面中的所有方法自動地屬於public。

介面中可以定義常量。介面不能包含例項域。

提供例項域和方法實現的任務應該由實現介面的那個類來完成。因此,可以將介面看成是沒有例項域的抽象類。

介面不是類,尤其不能使用new運算子例項化一個介面。

不能構造介面的物件,但可以宣告介面的變數。

介面變數必須引用實現了介面的類物件。

介面中的域被自動設為public static final。

如果先在一個介面中將一個方法定義為預設方法,然後又在超類或另一個介面中定義了同樣的方法。Java規則如下:

(1)超類有限。如果超類提供了一個具體方法,同名且有相同的引數型別的預設方法會被忽略。

(2)介面衝突。如果一個超介面提供了一個預設方法,另一個介面提供了同名且引數型別(不論是否預設引數)相同的方法,必須覆蓋這個方法來解決衝突。

回撥是一種常見的程式設計模式。在這種模式中,可以指出某個特定事件發生時應該採取的動作。

lambda表示式是一個可傳遞的程式碼塊,可以在以後執行一次或多次。

lambda表示式由3個部分:

  1. 一個程式碼塊
  2. 引數
  3. 自由變數的值,這是指非引數且不再程式碼中定義的變數。

規則:lambda表示式中捕獲的變數必須是實際上的最終變數。實際上的最終變數是指這個變數初始化之後就不會再為它賦新值。lamdba表示式與巢狀塊有相同的作用域。這裡同樣適用命名衝突和遮蔽的有關規則。在方法中,不能有兩個同名的區域性變數,因此,lambda表示式中同樣也不能有同名的區域性變數。在一個lambda表示式中使用this關鍵字時,是指建立這個lambda表示式的方法的this引數。

使用lambda表示式的重點是延遲執行。畢竟,如果想要立即執行程式碼,完全可以直接執行,而無需把它包裝在一個lambda表示式中。之所以希望以後再執行程式碼,這有很多原因:

  • 在一個單獨的執行緒中執行程式碼
  • 多次執行程式碼
  • 在演算法的適當位置執行程式碼
  • 發生某種情況時執行程式碼
  • 在必要時才執行程式碼

內部類是定義在另一個類中的類。使用內部類的原因是:

  • 內部類方法可以訪問該類定義所在的作用域中的資料,包括私有的資料
  • 內部類可以對同一個包中的其他類隱藏起來。
  • 當想要定義一個回撥函式且不想編寫大量程式碼時,使用匿名內部類比較便捷。

靜態內部類,這種內部類只是為了把一個類隱藏在另外一個類的內部,並不需要內部類引用外圍類物件。為此,可以將內部類宣告為static,以便取消產生的引用。

代理

利用代理可以在執行時建立一個實現了一組給定介面的新類。這種功能只有在編譯時無法確定需要實現哪個介面時才有必要使用。

代理類可以在執行時建立全新的類。這樣的代理類能夠實現指定的介面。尤其是,它具有下列方法:

  • 指定介面所需要的全部方法
  • Object類中的全部方法

然而,不能再執行時定義這些方法的新程式碼,而是要提供一個呼叫處理器。呼叫處理器是實現了InvocationHandler介面的類物件。在這個介面中只有一個方法:invoke。

無論何時呼叫代理物件的方法,呼叫處理器的invoke方法都會被呼叫,並向其傳遞Method物件和原始的呼叫引數。呼叫處理器必須給出處理帶哦用的方法。

建立一個代理物件,需要使用Proxy類的newProxyInstance方法。這個方法有三個引數:

  • 一個類載入器。作為Java安全模型的一部分,對於系統類和從因特網上下載下來的類,可以使用不同的類載入器。
  • 一個Class物件陣列,每個元素都是需要實現的介面。
  • 一個呼叫處理器

使用代理可能處於很多原因,例如:

  • 路由對遠端伺服器的方法呼叫
  • 在程式執行期間,將使用者介面事件與動作關聯起來
  • 為除錯,跟蹤方法呼叫

代理類是在程式執行過程中建立的。一旦被建立,就變成了常規類,與虛擬機器中的任何其他類沒有什麼區別。

所有的代理類都擴充套件於Proxy類。一個代理類只有一個例項域--呼叫處理器,它定義在Proxy的超類中。為了履行代理物件的職責,所需要的任何附加資料都必須儲存在呼叫處理器中。

所有代理類都覆蓋了Object類中的toString、equals和hashCode。如同所有的代理方法一樣,這些方法僅僅呼叫了呼叫處理器的invoke。Object類中的其他方法沒有被重新定義。

對於特定的類載入器和預設的一組介面來說,只能有一個代理類。也就是說,如果使用同一個類載入器和介面陣列呼叫兩次newProxyInstance方法的話,那麼久只能夠得到同一個類的兩個物件,也可以利用getProxyClass方法獲得這個類。

代理類一定是public和final。如果代理類實現的所有介面都是public,代理類就不屬於某個特定的報。否則,所有非公有的介面都必須屬於同一個包。

可以通過呼叫Proxy類中的isProxyClass方法檢測一個特定的Class物件是否代表一個代理類。