极简的艺术-方法引用
在JDK1.8中,方法引用同Lambda表达式一齐作为新特性被引用。它是一种比Lambda表达式更加简便的书写方式,旨在使用通用的解决方案来减少代码冗余。
下面先介绍使用,再进一步思考。
一、书写格式
方法引用符:::
,它所在的表达式被称为方法引用
格式:引用类::引用的方法
示例:System.out::println
二、使用方式
下面通过使用方式来认识方法引用
1.引用类方法
引用类方法,即引用类的静态方法。
格式:类名::静态方法
示例:
以引用Integer.parseInt
为例。设存在一个接口Interface01,其中只包含一个抽象方法,希望实现类可以实现将传入的字符串转换为int类型。
public interface Interface01 {
int toInt(String s);
}
在测试方法seeInt中,使用了该接口的toInt方法
private static void seeInt(Interface01 i){
int i1 = i.toInt("666");
//通过运算符,可以在调用后通过输出结果看出 i1 是String还是int
System.out.println(i1+222);
}
现在使用测试类来提供接口的实现。此处提供三种实现方式以便于比较
public class Demo1 {
public static void main(String[] args) {
//我们常用Integer.parseInt来实现将String转换为int
//匿名内部类方式。
seeInt(new Interface01() {
@Override
public int toInt(String s) {
return Integer.parseInt(s);
}
});
//Lambda表达式
seeInt(s -> Integer.parseInt(s));
//方法引用。
//引用Integer类中的parseInt静态方法
seeInt(Integer::parseInt);
}
private static void seeInt(Interface01 i){
int i1 = i.toInt("666");
//通过运算符,可以在调用后通过输出结果看出 i1 是String还是int
System.out.println(i1+222);
}
}
得到输出结果
888
888
888
在该例中,将String转换为int已经有一个成熟的解决方案,即Integer.parseInt
。所以直接引用了该方法。此时,Integer.parseInt就是Interface01接口中toInt抽象方法的具体实现
此时出现一个疑问,引用的这个方法是怎么处理参数的?
我们可以对比一下:
- toInt方法需要一个入参(String),返回一个出参(int)
- Integer.parseInt重载中存在一个方法是 需要一个入参(String),返回一个出参(int)
此时两者可以对应上,编译器将自动处理传参问题。
2.引用对象的实例方法
引用对象的实例方法。和引用类的静态方法在使用上没有什么区别只是将类变更为对象。注意:对象需要实例化
格式:对象名::方法名
示例:
public class Demo3 {
public static void main(String[] args) {
//引用对象的实例方法。和静态方法没有使用上的区别只是要new一下
Demo3 demo3 = new Demo3();
useInterface(demo3::method1);
}
private static void useInterface(Interface03 i){
i.abMethod1();
}
public void method1(){
System.out.println("111");
System.out.println("222");
System.out.println("333");
}
}
interface Interface03 {
void abMethod1();
}
3.特殊类型的实例方法
java中存在某些特殊方法。
以"".subString([start],[end])
为例,它在使用时需要三个参数,即
- 被截取的字符串(“”)
- 截取的开始下标([start])
- 截取的结束下标([end])
**示例:**使用Lambda和方法引用使用格式为:
public static void main(String[] args) {
//lambda
testInterface((s,start,end) -> s.substring(start,end));
/*
方法引用
第一个参数作为方法调用者
后面的参数作为方法的参数
*/
testInterface(String::substring);
}
4.构造方法引用
直接上代码演示
格式:类名::new
示例:
public static void main(String[] args) {
//Lambda
seeStudent((name,age) -> {
return new Student(name,age);
});
//方法引用 他的形式参数全部传递给构造器
seeStudent(Student::new);
}
思考
学习一个新知识的时候,我总有这样的疑问:为什么要学它,什么时候去用它,怎么用它呢?(这个和高中作文的议论文格式一样…看来学议论文还是有帮助的=。=)
所以此处的问题是:为什么需要方法引用,什么时候使用方法引用呢?
在方法引用的学习时,我产生了这样的思考
- 当接口只需要实现一次 -> 使用匿名内部类
- 作为匿名内部类的简便写法 -> 使用Lambda表达式
- 当Lambda的实现存在通用解决方案 -> 使用方法引用
当”一个接口/类的方法的某个实现方式在程序中只会执行一次“时,为了减少代码量,我们会使用匿名内部类。
而使用方法引用会引用一个通用解决方案,此时该解决方案就不属于”只使用一次”的了。
换言之,
当程序中使用到接口,接口在某个类中已存在实现方式,就可以考虑使用“方法引用”的方式来简化书写
总结:
- 方法引用是Lambda的一种简便写法
- 使用方法引用可以减少重复代码,减少冗余