Java複習第12天---12.1---Java8新特性---方法引用

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方法進行輸出
  • 注意

    1. System.out對象已經存在
    2. 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
    
  • 通過對象名引用方法使用前提:

    1. 使用的對象必須存在
    2. 使用的對象的方法必須存在

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章