Java新特性-方法引用
方法引用的出现原因
在使用 Lambda 表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿参数做操作, 如果我们在 Lambda 中所指定的操作方案,已经有地方存在相同方案, 就可以通过方法引用来使用已经存在的方案
体验方法的引用
新建一个 Printable 接口
/** * @author QY */ public interface Printable { void printString(String s); }
方法引用符::: 参数传给了 System 当中
/** * @author QY */ public class PrintableMain { public static void main(String[] args) { usePrintable(System.out::println); } private static void usePrintable(Printable printable) { printable.printString("test"); } }
方法引用符
:: 该符号为引用运算符,而它所在的表达式被称为方法引用
推导与省略
如果使用 Lambda,那么根据 “可推导就是可省略” 的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导
如果使用方法引用,也是同样可以根据上下文进行推导
方法引用是 Lambda 的孪生兄弟
引用类方法
引用类方法,其实就是引用类的静态方法,格式:类名::静态方法,下面将给出一段示例进行参考,首先新建一个 Converter 接口
/** * @author QY */ public interface Converter { Number convert(String str); }
然后 psvm 进行使用一下如下
/** * @author QY */ public class ConverterMain { public static void main(String[] args) { useConverter((String str) -> { return Integer.parseInt(str); }); } private static void useConverter(Converter converter) { System.out.println(converter.convert("6666")); } }
如上的写法存在简化的写法,一步一步来进行改造,首先先来改造一下 Lambda 的简写写法,改造之后如下
/** * @author QY */ public class ConverterMain { public static void main(String[] args) { useConverter(str -> Integer.parseInt(str)); } private static void useConverter(Converter converter) { System.out.println(converter.convert("6666")); } }
Lambda 表达式的改造完成了,那么就来开始看看引用类方法吧,进行改造如下, Lambda 表达式被类方法替代的时候,它的形式参数全部传递给静态方法作为参数
/** * @author QY */ public class ConverterMain { public static void main(String[] args) { useConverter(Integer::parseInt); } private static void useConverter(Converter converter) { System.out.println(converter.convert("6666")); } }
引用对象方法
格式:对象::成员方法 不多说什么直接上案例了,自行参考,新建一个 CalculateInterface 接口
/** * @author QY */ public interface CalculateInterface { void calculate(Integer numOne, Integer numTwo); }
然后在新建一个 CalculateString 普通的类
/** * @author QY */ public class CalculateString { public void printCalculate(Integer numOne, Integer numTwo) { System.out.println(numOne + numTwo); } }
在进行 psvm 进行测试使用如下
/** * @author QY */ public class CalculateString { public void printCalculate(Integer numOne, Integer numTwo) { System.out.println(numOne + numTwo); } }
我没有写的一步到位,主要是为了更好了让阅读者看到一步一步简化和演变的过程,进行改造 Lambda 的简写写法如下
/** * @author QY */ public class CalculateMain { public static void main(String[] args) { useCalculate((a, b) -> System.out.println(a + b)); } private static void useCalculate(CalculateInterface calculateInterface) { calculateInterface.calculate(1, 2); } }
改造就到这,接下来开始就来看看对象方法的引用吧,首先我实例化了一个对象,然后在调用 useCalculate 里面就可以进行对象方法的引用了,Lambda 表达式被对象的实例方法替代的时候,它的形式参数全部传递给了该方法作为参数, 如下所示
/** * @author QY */ public class CalculateMain { public static void main(String[] args) { CalculateString calculateString = new CalculateString(); useCalculate(calculateString::printCalculate); } private static void useCalculate(CalculateInterface calculateInterface) { calculateInterface.calculate(1, 2); } }
引用类的实例方法
格式和上面的一样不在介绍,废话不多说直接上代码,新建一个 MyString 接口
/** * @author QY */ public interface MyString { String mySubString(String s, int x, int y); }
老规矩,先来看看最初的 Lambda 写法
/** * @author QY */ public class MyStringMain { public static void main(String[] args) { useMyString((String s, int x, int y) -> { return s.substring(x, y); }); } private static void useMyString(MyString myString) { System.out.println(myString.mySubString("HelloWorld", 2, 5)); } }
Lambda 简化写法,至于简化的原理我之前的 Lambda 文章已经解释过了
/** * @author QY */ public class MyStringMain { public static void main(String[] args) { useMyString((s, x, y) -> s.substring(x, y)); } private static void useMyString(MyString myString) { System.out.println(myString.mySubString("HelloWorld", 2, 5)); } }
引用类的实例方法,Lambda 表达式被类的实例方法替代的时候,第一个参数作为调用者,后面的参数全部传递给了该方法作为参数,例如第一个参数就是我们上方写的 HelloWorld 它作为调用者,后面的参数全部传递给了该方法作为参数,改造之后的内容如下所示
/** * @author QY */ public class MyStringMain { public static void main(String[] args) { useMyString(String::substring); } private static void useMyString(MyString myString) { System.out.println(myString.mySubString("HelloWorld", 2, 5)); } }
引用构造器
引用构造器,其实就是引用构造方法,废话不多说直接上代码,使用格式同上,新建一个 Person 类
/** * @author QY */ public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
在新建一个 PersonBuildInterface 接口
/** * @author QY */ public interface PersonBuildInterface { Person build(String name, int age); }
psvm 进行测试如下,和之前一样的一步一步简化到最终的简化代码
/** * @author QY */ public class PersonMain { public static void main(String[] args) { usePersonBuilder((name, age) -> { return new Person(name, age); }); } private static void usePersonBuilder(PersonBuildInterface personBuildInterface) { Person bnTangPerson = personBuildInterface.build("BNTang", 23); System.out.println(bnTangPerson.getName() + "," + bnTangPerson.getAge()); } }
简化 Lambda 写法
/** * @author QY */ public class PersonMain { public static void main(String[] args) { usePersonBuilder((name, age) -> new Person(name, age)); } private static void usePersonBuilder(PersonBuildInterface personBuildInterface) { Person bnTangPerson = personBuildInterface.build("BNTang", 23); System.out.println(bnTangPerson.getName() + "," + bnTangPerson.getAge()); } }
改造引用构造器
/** * @author QY */ public class PersonMain { public static void main(String[] args) { usePersonBuilder(Person::new); } private static void usePersonBuilder(PersonBuildInterface personBuildInterface) { Person bnTangPerson = personBuildInterface.build("BNTang", 23); System.out.println(bnTangPerson.getName() + "," + bnTangPerson.getAge()); } }
使用说明:Lambda 表达式被构造器替代的时候,它的形式参数全部传递给了构造器作为参数