發表文章

Java 泛型 (Generic) 的 Covariance, Contravariance, 以及 Invariance

 Covariance,Contravariance,Invariance          把 A、B 想成類別,F 想成某種轉換,如 F(A) 表示把 A 轉換成其他形式, ≤ 符號表示子類別關係,如 A ≤ B 表示 A 是 B 的子類別。有這些後,可以簡單說明 Covariance、Contravariance 以及 Invariance 的意思: Covariance:A ≤ B 可以得出 F(A) ≤ F(B),則稱 F 具有 Covariance。 Contravariance:A ≤ B 可以得出 F(B) ≤ F(A),則稱 F 具有 Contravariance。 Invariance:F 既不是 Covariance 也不是 Contravariance 時,就稱 F 為 Invariance。  Java 中的 Covariance          假設我們定義了以下的類別:FujiApple  ≤ Apple ≤ Fruit ≤ Food,Orange ≤ Fruit ≤ Food。稍微熟悉 Java 語法的人,很快就能了解 Java 的 Array 是 Covariance,也就是說 Apple[] 可以是 Fruit [] 。那我們能利用這樣的特性做什麼事呢?  // 初始化一個 Apple array Apple[] apples = new Apple[10]; // Apple ≤ Food,所以這樣是可以的 Food[] foods = apples; // 從 Food array 取出 Food 本來就沒問題 Food f = foods[0]; // Oh my god !! Error foods[1] = new Orange();         從上面的幾行程式碼我們可以看到,把 Apple array 指給 Food array 是沒問題的,因為 Apple 是一種 Food,同理取出 Food array 裡...

為什麼 GUI framework 大多都是 single-threaded (not thread safe)

        主要原因為有兩個不同方向的 operation:GUI activity 跟 input event。 GUI activity 是由 UI 最上層 app code 一路到底層 OS, 而 input event 則是相反,從底層 OS 一路往上到 app code。         要用 lock 來保護不同方向的 operation 很難,很容易 deadlock, 所以比較省事的方法就是所有 GUI activity 都用一個 thread 處理 (一種 event driven 的概念), 這樣另一個方向的 input event 就能當成是一種「event」。 參考資料:      Multithreaded toolkits: A failed dream?      Why must/should UI frameworks be single threaded?      Why are most UI frameworks single threaded?      Why is a single threaded model used to update the UI as main thread?      What does threadsafe mean?

transient 介紹

        某天無意間看到了 ArrayList 的 source code,發現了一個沒看過的關鍵字:transient。寫 Android 也有幾年了,卻對 transient 完全沒概念。 Google 了一下,才知道這個關鍵字通常都是搭配 Serializable 來使用的。  什麼是 Serializable          Serializable 是為了要讓 物件能序列化 而必需要實作的 marker interface。而序列化簡單說就是能 將記憶體(Memory)中的實體物件(Object Instance)以位元流(byte stream)方式儲存於永久媒體如硬碟 。之後也能從永久媒體讀取物件到記憶體,並回復到先前狀態。除了存在永久媒體之外,也可以用在網路溝通,如 socket 或 RMI。  什麼是 transient           transient 為 Java 內部的一個關鍵字,其目的是告訴 JVM 有加 transient 的 member variable 不要被序列化 。因為有時候我們會希望物件能序列化,但內部有些資料卻不要記錄,像是個人資料如密碼等。如以下的程式碼: public class Foo implements Serializable { private String saveMe; private transient SomeObject dontSaveMe; private transient String password; private transient int dontSaveInt; //... }         JVM 就不會把 class dontSaveMe,String password,int dontSaveInt 序列化。   Java  Serializable 序列化規則   Class 中所有 primitive type 預設都是可以序列化。 成員變數 (prim...

volatile 介紹

        volatile 關鍵字 只能用在 variable ,不能用在 method 或是 class,其目的是告訴 Java compiler 或是 Thread, 讀取 variable 的值都要從 main memory 去讀取 。因此假如你想讓 int , boolean  等 variable 的 讀值或是寫值的行為是 atomic ,就可以使用 volatile。         從 Java 5 之後,宣告為 volatile 的 variable 就具有 " happens-before relationship ",且可以防止 Java compiler 對程式碼做 reorder 來達到最佳化的效果。         用程式碼來解釋 volatile 的用法,比較簡單的範例就是  Singleton Pattern : public class Singleton { // 利用 volatile, 可以保證此變數的值是一致的 private volatile static Singleton sInstance; private Singleton(){} public static Singleton getInstance() { // 只有第一次建立物件才會完整執行此段程式 if(sInstance == null) { synchronized (Singleton.class) { // 進入同步區後再檢查一次, // 還是 null 才建立實體 if(sInstance == null) { sInstance = new Singleton(); } } } return sInsta...

為什麼 abstract method 不能用 synchronized ?

        因為 synchronized method 取得的鎖是該 class 的 instance。class 有 abstract method,則 class 也要宣告為 abstract,而 abstract class 是不能被實例化的,因此就不能有 abstract synchronized method。         另一種說法是一個 method 是否為 synchronized 是看 method 的內容,也就是 method 的 implementation detail,而 abstract method 只定義了 interface,並沒有實做,自然也就不能用 synchronized。可參考  http://stackoverflow.com/questions/12805698/why-cant-an-abstract-method-be-synchronized         個人比較傾向第二種說法,因為 abstract class 裡其他有 implementation 的 method 還是能用 this,第一種說法比較不通。