lambda 重點高級知識講解1 - 實例方法的方法引用
本文由曉風輕編寫,不講解lambda的初級入門知識,只講解lambda中高級的/難的重點知識。
實例方法的方法引用
方法引用有多種,靜態方法的方法引用很好理解,但實例對象的方法引用一開始確實讓我有點費解,這和靜態方法引用由啥區別?看上去很像啊。
class DemoClass { /** * 這裡是一個靜態方法 */ public static int staticMethod(int i) { return i * 2; } /** * 這裡是一個實例方法 */ public int normalMethod(int i) { System.out.println("實例方法可以訪問this:" + this); return i * 3; }}public class MethodRefrenceDemo { public static void main(String[] args) { // 靜態方法的方法引用 IntUnaryOperator methodRefrence1 = DemoClass::staticMethod; System.out.println(methodRefrence1.applyAsInt(111)); DemoClass demo = new DemoClass(); // 實例方法的方法引用 IntUnaryOperator methodRefrence2 = demo::normalMethod; System.out.println(methodRefrence2.applyAsInt(111)); }}
這裡牽涉到不同的語言裡面對this的實現方法。我們知道靜態方法和實例方法的區別是實例方法有this,靜態方法沒有。java裡面是怎麼樣實現this的呢?
java裡面在默認把this作為參數,放到實例方法的第一個參數。
就是說:
/** * 這裡是一個實例方法 */ public int normalMethod(int i) { System.out.println("實例方法可以訪問this:" + this); return i * 2; }
編譯之後和下面這樣的代碼編譯之後是一樣的!
/** * 這裡是一個實例方法 */ public int normalMethod(DemoClass this,int i) { System.out.println("實例方法可以訪問this:" + this); return i * 2; }
如何證明?
第1個證據,看反編譯裡面的本地變數表。
靜態方法:
而實例方法
第2個證據,下面這樣的代碼能正確執行。
class DemoCl2{ /** * 這裡是一個實例方法, 代碼上2個參數 * 而我們調用的時候只有一個參數 */ public int normalMethod(DemoClass2 this,int i) { return i * 2; }}public class MethodRefrenceDemo { public static void main(String[] args) { DemoClass2 demo2 = new DemoClass2(); // 代碼定義上有2個參數, 第一個參數為this // 但實際上調用的時候只需要一個參數 demo2.normalMethod(1); }}
所以,我的理解,java裡面的所有方法都是靜態方法,只是有些方法有this變數,有些沒有。不知道這樣理解是否正確。
所以,成員方法我們也可以寫成靜態方法的方法引用。如下:
public class MethodRefrenceDemo { public static void main(String[] args) { // 靜態方法的方法引用 IntUnaryOperator methodRefrence1 = DemoClass::staticMethod; System.out.println(methodRefrence1.applyAsInt(111)); DemoClass demo = new DemoClass(); // 實例方法normalMethod的方法引用 IntUnaryOperator methodRefrence2 = demo::normalMethod; System.out.println(methodRefrence2.applyAsInt(111)); // 對同一個實例方法normalMethod也可以使用靜態引用 // 代碼上normalMethod雖然只有一個參數,但實際上有一個隱含的this函數 // 所以使用的是2個參數bifunction函數介面 BiFunction<DemoClass, Integer, Integer> methodRefrence3 = DemoClass::normalMethod; System.out.println(methodRefrence3.apply(demo, 111)); }}
上面代碼裡面。對同一個實例方法normalMethod,我們既可以使用實例方法引用(實例::方法名),也可以使用靜態方法引用(類名::方法名)。
下一節講級聯lambda表達式。
推薦閱讀:
TAG:Lambda表達式 | 函數式編程 | FunctionalReactiveProgramming |