Java 8 加入了 lambda expression 賦予了 Java 新的能力, 在使用 lambda 的同時常發現神奇的 :: 雙冒號 (double colon) 穿插其中, :: 代表什麼意義呢?
舉例來說, 在過去我們要做個由小到大的數列排序,當然使用 java.util.Arrays.sort(Object[] a) 是最快的方式, 如果要自訂排序方式使用 anonymous inner class 是最簡便的方式
例 1 : 使用 anonymous inner class
例 2 : 使用 lambda expression
例 3 : 使用 method reference
:: 雙冒號 (double colon) 是 Java 8 加入的新 operator, 稱作 Method Reference, Method Reference 提供式四個種類的用法
1. Reference to a static method
前面例3 Arrays.sort(ary, Integer::compare) 就屬此類, Integer.compare 是 static method
2. Reference to an instance method of a particular object
使用 instance method, 傳入參數與回傳型別必須與 interface 的 compare method 定義一致
使用 instance method, 與前例比較原本是傳入兩個參數 (int a, int b) 回傳一個 int, 轉換為 a.compareTo(b) 的形式, 同樣都回傳 int
Reference to a Constructor 相較其他三個比較複雜些,用下面的例子來說明,首先創建 ICarFactory interface 和 CarBean class
Java 8 可使用 lambda expression, 實作可改寫成如下的方式,簡潔許多
舉例來說, 在過去我們要做個由小到大的數列排序,當然使用 java.util.Arrays.sort(Object[] a) 是最快的方式, 如果要自訂排序方式使用 anonymous inner class 是最簡便的方式
例 1 : 使用 anonymous inner class
Integer[] ary = new Integer[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 }; // anonymous inner class Arrays.sort(ary, new ComparatorJava 8 之後你可以這樣寫() { @Override public int compare(Integer a, Integer b) { return Integer.compare(a, b); } }); System.out.println(Arrays.toString(ary));
例 2 : 使用 lambda expression
Integer[] ary = new Integer[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 }; // lambda expression Arrays.sort(ary, (a, b) -> Integer.compare(a, b)); System.out.println(Arrays.toString(ary));是不是簡潔了很多呢? 但是我們發現 (a, b) -> Integer.compare(a, b)), 傳入兩個 Integer parameter 再 return Integer 不就跟 Integer.compare 一樣嗎? (a, b) -> 感覺好像是多餘的,因此有更精簡的做法, 就是使用 lambda expression 的 method reference
例 3 : 使用 method reference
Integer[] ary = new Integer[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 }; // method reference Arrays.sort(ary, Integer::compare); System.out.println(Arrays.toString(ary));
:: 雙冒號 (double colon) 是 Java 8 加入的新 operator, 稱作 Method Reference, Method Reference 提供式四個種類的用法
1. Reference to a static method
前面例3 Arrays.sort(ary, Integer::compare) 就屬此類, Integer.compare 是 static method
2. Reference to an instance method of a particular object
使用 instance method, 傳入參數與回傳型別必須與 interface 的 compare method 定義一致
class MyCompare { public int compareInt(int a, int b) { return a - b; } } Integer[] ary = new Integer[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 }; MyCompare my = new MyCompare(); Arrays.sort(ary, my::compareInt); System.out.println(Arrays.toString(ary));3. Reference to an instance method of an arbitrary object of a particular type
使用 instance method, 與前例比較原本是傳入兩個參數 (int a, int b) 回傳一個 int, 轉換為 a.compareTo(b) 的形式, 同樣都回傳 int
Integer[] ary = new Integer[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 }; Arrays.sort(ary, Integer::compareTo); System.out.println(Arrays.toString(ary));4. Reference to a Constructor
Reference to a Constructor 相較其他三個比較複雜些,用下面的例子來說明,首先創建 ICarFactory interface 和 CarBean class
interface ICarFactory { CarBean getCar(String color, int year); } class CarBean { private String name; private int maxSpeed; CarBean(String name, int maxSpeed) { this.name = name; this.maxSpeed = maxSpeed; } String getName() { return name; } int getMaxSpeed() { return maxSpeed; } }要實作 ICarFactory, 傳統的方法是使用 "implements" 關鍵字來實作介面
Java 8 可使用 lambda expression, 實作可改寫成如下的方式,簡潔許多
ICarFactory f = (String name, int maxSpeed) -> { return new CarBean(name, maxSpeed); };仔細觀察可發現,Interface 所定義的 getCar(String color, int year) 和 CarBean(String name, int maxSpeed) 傳入參數型別正好一樣,因此可使用 method reference => Reference to a Constructor 的方式,再把寫法簡化
ICarFactory f = CarBean::new;測試 Reference to a Constructor
//ICarFactory f = (String name, int maxSpeed) -> { return new CarBean(name, maxSpeed); }; ICarFactory f = CarBean::new; CarBean c = f.getCar("GTR", 300); System.out.println("Car Name:" + c.getName() + " / Max Speed:" + c.getMaxSpeed());使用 lambda 或 method reference 可有效的讓程式碼更簡短,也提供程式更大的彈性,不管用以上哪一種寫法都是由編譯器來做推斷和解釋完成,這是使用上需要留意的部分