Java複習第12天---12.1---Java8新特性---方法引用
目錄
文章目錄
內容
1、簡介
方法引用,是用來簡化Lambda表達式的。如果在Lambda表達式中的操作,已經存在相同的方案,那麼就可以使用方法引用簡化。通過下面的例子簡單認識下:
1.1、冗餘的Lambda場景
-
Lambda表達式簡單使用:接收字符串參數,然後打印
-
代碼1.1-1:
package feature.jdk8.methodReference; @FunctionalInterface public interface Printable { void print(String s); } package feature.jdk8.methodReference; public class TestPrintable { public static void main(String[] args) { printString("Hello", s -> System.out.println(s)); } public static void printString(String s, Printable p) { p.print(s); } } 測試結果: Hello
-
分析:
- Lambda表達式的目的,打印參數傳遞的字符串
- 把參數s,傳遞給了System.out對象,調用out對象的println方法進行輸出
-
注意
- System.out對象已經存在
- println方法也應存在
那麼我們就可以使用方法引用優化Lambda表達式,可以使用System.out直接調用println方法。
1.2、方法引用簡化
-
代碼1.1-2:
package feature.jdk8.methodReference; public class TestPrintable { public static void main(String[] args) { printString("Hello", s -> System.out.println(s)); printString("Hello", System.out::println); // 方法引用 } public static void printString(String s, Printable p) { p.print(s); } } 測試結果: Hello Hello
2、方法引用符
雙冒號::爲引用運算符,而它所在的表達式被稱爲方法引用。如果Lambda要表達的函數方案已經存在於某個方法的實現中,那麼則可以通過雙冒號來引用該方法作爲Lambda的替代。
- 前提:Lambda要表達的函數方案已經存在於某個方法的實現中
2.1、語義分析
1.1Lambda表達式對比:
-
Lambda表達式寫法:s -> System.out.println(s);
-
方法引用寫法:System.out::println
-
第一種語義:拿到參數之後經Lambda之手,傳遞給System.out.println方法輸出
-
第二種:直接讓System.out中的println方法取代Lambda。
兩種寫法的執行效果相同,而第二種方法引用複用了已有方案,更加簡潔。
2.2、推導與省略
如果使用Lambda,那麼根據可推導就是可省略的原則,無需知道參數,也無需指定的重載形式–它們都將被自動推導。而如果使用方法引用,同樣可以根據上下文進行推導。
函數式接口是Lambda的基礎,而方法引用是Lambda的孿生兄弟。
-
案例2.2:重載方法的自動推導
package feature.jdk8.methodReference; public class TestPrintable2 { public static void main(String[] args) { printInt(10, System.out::println); printInt(10, 20, System.out::println); } public static void printInt(int a, Printable<Integer> p) { p.print(a); } public static void printInt(int a, int b, Printable<Integer> p) { p.print(a + b); } } 測試結果: 10 30
2、通過對象名引用成員方法
這是最常見的一種用法,與上例相同。
-
示例2-1:
package feature.jdk8.methodReference; @FunctionalInterface public interface Printable<T> { void print(T t); } package feature.jdk8.methodReference; public class StringDemo { public void printUpperCase(String str) { System.out.print(str.toUpperCase()); } } package feature.jdk8.methodReference; public class TestMethod1 { public static void main(String[] args) { StringDemo sd = new StringDemo(); printUpperCase("Java", sd::printUpperCase); } public static void printUpperCase(String s, Printable<String> p) { p.print(s); } } 測試結果: JAVA
-
通過對象名引用方法使用前提:
- 使用的對象必須存在
- 使用的對象的方法必須存在
3、通過類名引用靜態方法
-
示例3-1:打印整數的絕對值
package feature.jdk8.methodReference; @FunctionalInterface public interface CalcAbs { int abs(int i); } package feature.jdk8.methodReference; public class TestClassStatic { public static void main(String[] args) { int n = -220; System.out.println(absMethod(n, Math::abs)); } // 求整數的絕對值 public static int absMethod(int i, CalcAbs c) { return c.abs(i); } } 測試結果: 220
-
類的靜態方法引用前提:
- 類存在
- 類中存在相應的靜態方法
4、通過super引用父類方法
-
示例4-1:
package feature.jdk8.methodReference; @FunctionalInterface public interface Greetable { void greet(); } package feature.jdk8.methodReference; public class Human { public void sayHello() { System.out.println("Hello"); } } package feature.jdk8.methodReference; public class Man extends Human{ @Override public void sayHello() { System.out.println("Hello, 我是man"); } public void method(Greetable g) { g.greet(); } public void show() { // 調用super的sayHello方法 this.method(super::sayHello); } } package feature.jdk8.methodReference; public class TestSuperRef { public static void main(String[] args) { Man m = new Man(); m.show(); m.sayHello(); } } 測試結果: Hello Hello, 我是man
5、通過this引用本類的方法
-
示例5-1:
-
函數式接口代碼,Human代碼,測試類代碼同上
-
Man類稍做修改如下5-1:
package feature.jdk8.methodReference; public class Man extends Human{ @Override public void sayHello() { System.out.println("Hello, 我是man"); } public void method(Greetable g) { g.greet(); } public void show() { // 調用super的sayHello方法 this.method(this::sayHello); } } 測試結果: Hello, 我是man Hello, 我是man
6、類的構造器引用
-
示例6-1:
package feature.jdk8.methodReference; @FunctionalInterface public interface PersonBuilder { Person create(String name); // 根據給定的名稱創建人類對象 } package feature.jdk8.methodReference; public class Person { private String name; public Person() {} public Person(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person [name=" + name + "]"; } } package feature.jdk8.methodReference; public class TestConstructorRef { public static void main(String[] args) { print("Rick", Person::new); } public static void print(String name, PersonBuilder pb) { System.out.println(pb.create(name)); } } 測試結果: Person [name=Rick]
7、數組的構造器引用
-
示例7-1:
package feature.jdk8.methodReference; public interface ArrayBuilder { int[] builder(int len); // 返回指定長度的整形數組 } package feature.jdk8.methodReference; import java.util.Arrays; public class TestArrayRef { public static void main(String[] args) { int[] arr = initArray(5, int[]::new); for(int i = 0; i < arr.length; i++) { arr[i] = i; } System.out.println(Arrays.toString(arr)); } public static int[] initArray(int len, ArrayBuilder ab) { return ab.builder(len); } } 測試結果: [0, 1, 2, 3, 4]
後記 :
本項目爲參考某馬視頻開發,相關視頻及配套資料可自行度娘或者聯繫本人。上面爲自己編寫的開發文檔,持續更新。歡迎交流,本人QQ:806797785
前端項目源代碼地址:https://gitee.com/gaogzhen/vue-leyou
後端JAVA源代碼地址:https://gitee.com/gaogzhen/JAVA