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 |