在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿什么参数做什么操作。那么考虑 一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑?
冗余的Lambda场景
来看一个简单的函数式接口以应用Lambda表达式:
@FunctionalInterfaceinterface InnerPrintfString {void print(String string);}public class PrintfString {public static void main(String[] args) {print((s) -> System.out.println(s));}public static void print(InnerPrintfString iPrintfString) {iPrintfString.print("Hello Word");}}
问题分析:这段代码的问题在于,对字符串进行控制台打印输出的操作方案,明明已经有了现成的实现,那就是 System.out 对象中的 println(String) 方法。
既然Lambda希望做的事情就是调用 println(String) 方法,那何必自己手动调 用呢?
用方法引用改进代码
@FunctionalInterfaceinterface InnerPrintfString {void print(String string);}public class PrintfString {public static void main(String[] args) {print(System.out::println); //方法引用}public static void print(InnerPrintfString iPrintfString) {iPrintfString.print("Hello Word");}}
⚠️注意: 其中的双冒号 :: 写法,这被称为“方法引用”,而双冒号是一种新的语法
方法引用定义
Lambda表达式写法s -> System.out.println(s);方法引用写法System.out::println
Lambda 中 传递的参数 一定是方法引用中 的那个方法可以接收的类型,否则会抛出异常
通过对象名引用成员方法
class Tool {public void printUpperCase(String string) {System.out.println(string.toUpperCase());}}@FunctionalInterfaceinterface PrintfString {void print(String string);}public class PrintfStringDemo {public static void main(String[] args) {Tool tool = new Tool();print(tool::printUpperCase); // HELLO WORD}private static void print(PrintfString printfString) {printfString.print("Hello Word");}}
通过类名称引用静态方法
interface Calculater {int abs(int num);}public class CalculaterDemo {public static void main(String[] args) {Object num = abs(CalculaterDemo::abs);System.out.println(num);}private static int abs(Calculater calculater) {return calculater.abs(-10);}private static int abs(int i) {return Math.abs(i);}}
通过super引用成员方法
@FunctionalInterfaceinterface Behavior {void say(String string);}class Person {public void sayHello(final String s) {System.out.println("【 " + s + " 】Hello Word");}}class Student extends Person {@Overridepublic void sayHello(final String s) {System.out.println("【 " + s + " 】Hello Word");}public void say(final Behavior behavior, final String string) {behavior.say(string);}public void show() {say(super::sayHello, "Student");}}public class TestDemo {public static void main(String[] args) {new Student().show();}}
通过this引用成员方法
@FunctionalInterfaceinterface Tool {void buy(String string);}class Person {public void buyHouse(final String s) {System.out.println("【 " + s + " 】买房子");}}class Businessman extends Person {@Overridepublic void buyHouse(final String s) {System.out.println("【 " + s + " 】买房子");}public void buy(final Tool tool, final String string) {tool.buy(string);}public void show() {buy(this::buyHouse, "Businessman");}}public class TestDemo {public static void main(String[] args) {new Businessman().show();}}
类的构造器引用
由于构造器的名称与类名完全一样,并不固定。所以构造器引用使用 类名称::new的格式表示
interface Info {Person buildPerson(String name);}class Person {private String name;// public static String idCard = "44142419990909";Person(String name) {this.name = name;};public String getName() {return this.name;}}public class TestDemo {public static String printName(String name, Info info) {return info.buildPerson(name).getName();}public static void main(String[] args) {String name = printName("Ken", Person::new);System.out.println(name);}}
数组的构造器引用
创建数组长度
import java.util.Arrays;@FunctionalInterfaceinterface ArrayBuild {int[] buildArray(int length);}public class TestDemo {public static void main(String[] args) {int[] arrays = initArray(10, int[]::new);System.out.println(Arrays.toString(arrays));}public static int[] initArray(int length,ArrayBuild arrayBuild) {return arrayBuild.buildArray(length);}}
