在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿什么参数做什么操作。那么考虑 一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑?

冗余的Lambda场景

来看一个简单的函数式接口以应用Lambda表达式:

  1. @FunctionalInterface
  2. interface InnerPrintfString {
  3. void print(String string);
  4. }
  5. public class PrintfString {
  6. public static void main(String[] args) {
  7. print((s) -> System.out.println(s));
  8. }
  9. public static void print(InnerPrintfString iPrintfString) {
  10. iPrintfString.print("Hello Word");
  11. }
  12. }

问题分析:这段代码的问题在于,对字符串进行控制台打印输出的操作方案,明明已经有了现成的实现,那就是 System.out 对象中的 println(String) 方法。
既然Lambda希望做的事情就是调用 println(String) 方法,那何必自己手动调 用呢?

用方法引用改进代码

  1. @FunctionalInterface
  2. interface InnerPrintfString {
  3. void print(String string);
  4. }
  5. public class PrintfString {
  6. public static void main(String[] args) {
  7. print(System.out::println); //方法引用
  8. }
  9. public static void print(InnerPrintfString iPrintfString) {
  10. iPrintfString.print("Hello Word");
  11. }
  12. }

⚠️注意: 其中的双冒号 :: 写法,这被称为“方法引用”,而双冒号是一种新的语法

方法引用定义

  1. Lambda表达式写法
  2. s -> System.out.println(s);
  3. 方法引用写法
  4. System.out::println

Lambda 中 传递的参数 一定是方法引用中 的那个方法可以接收的类型,否则会抛出异常

通过对象名引用成员方法

  1. class Tool {
  2. public void printUpperCase(String string) {
  3. System.out.println(string.toUpperCase());
  4. }
  5. }
  6. @FunctionalInterface
  7. interface PrintfString {
  8. void print(String string);
  9. }
  10. public class PrintfStringDemo {
  11. public static void main(String[] args) {
  12. Tool tool = new Tool();
  13. print(tool::printUpperCase); // HELLO WORD
  14. }
  15. private static void print(PrintfString printfString) {
  16. printfString.print("Hello Word");
  17. }
  18. }

通过类名称引用静态方法

  1. interface Calculater {
  2. int abs(int num);
  3. }
  4. public class CalculaterDemo {
  5. public static void main(String[] args) {
  6. Object num = abs(CalculaterDemo::abs);
  7. System.out.println(num);
  8. }
  9. private static int abs(Calculater calculater) {
  10. return calculater.abs(-10);
  11. }
  12. private static int abs(int i) {
  13. return Math.abs(i);
  14. }
  15. }

通过super引用成员方法

  1. @FunctionalInterface
  2. interface Behavior {
  3. void say(String string);
  4. }
  5. class Person {
  6. public void sayHello(final String s) {
  7. System.out.println("【 " + s + " 】Hello Word");
  8. }
  9. }
  10. class Student extends Person {
  11. @Override
  12. public void sayHello(final String s) {
  13. System.out.println("【 " + s + " 】Hello Word");
  14. }
  15. public void say(final Behavior behavior, final String string) {
  16. behavior.say(string);
  17. }
  18. public void show() {
  19. say(super::sayHello, "Student");
  20. }
  21. }
  22. public class TestDemo {
  23. public static void main(String[] args) {
  24. new Student().show();
  25. }
  26. }

通过this引用成员方法

  1. @FunctionalInterface
  2. interface Tool {
  3. void buy(String string);
  4. }
  5. class Person {
  6. public void buyHouse(final String s) {
  7. System.out.println("【 " + s + " 】买房子");
  8. }
  9. }
  10. class Businessman extends Person {
  11. @Override
  12. public void buyHouse(final String s) {
  13. System.out.println("【 " + s + " 】买房子");
  14. }
  15. public void buy(final Tool tool, final String string) {
  16. tool.buy(string);
  17. }
  18. public void show() {
  19. buy(this::buyHouse, "Businessman");
  20. }
  21. }
  22. public class TestDemo {
  23. public static void main(String[] args) {
  24. new Businessman().show();
  25. }
  26. }

类的构造器引用

由于构造器的名称与类名完全一样,并不固定。所以构造器引用使用 类名称::new的格式表示

  1. interface Info {
  2. Person buildPerson(String name);
  3. }
  4. class Person {
  5. private String name;
  6. // public static String idCard = "44142419990909";
  7. Person(String name) {
  8. this.name = name;
  9. };
  10. public String getName() {
  11. return this.name;
  12. }
  13. }
  14. public class TestDemo {
  15. public static String printName(String name, Info info) {
  16. return info.buildPerson(name).getName();
  17. }
  18. public static void main(String[] args) {
  19. String name = printName("Ken", Person::new);
  20. System.out.println(name);
  21. }
  22. }

数组的构造器引用

创建数组长度

  1. import java.util.Arrays;
  2. @FunctionalInterface
  3. interface ArrayBuild {
  4. int[] buildArray(int length);
  5. }
  6. public class TestDemo {
  7. public static void main(String[] args) {
  8. int[] arrays = initArray(10, int[]::new);
  9. System.out.println(Arrays.toString(arrays));
  10. }
  11. public static int[] initArray(int length,ArrayBuild arrayBuild) {
  12. return arrayBuild.buildArray(length);
  13. }
  14. }