最近几天在学依赖注入框架Dagger。可能是因为总是查阅kotlin把java给忘了,读实例代码的时候有时候反应不过来(比如System.out::println
的真正含义),不由得写点东西复习一下。。。
Dagger示例代码
- 网页链接
- 代码片段
1 2 3 4 5 6 7 8 9 10 11 12
interface Outputter { void output(String output); } ... @Module abstract class SystemOutModule { @Provides static Outputter textOutputter() { return System.out::println; } }
上述例子是为了说明
@provides
注解是用来向依赖注入请求提供实例的。方法textOutputter
显然返回Outputter
的实例,该实例(实现)通过System.out::println
得到。
Java方法引用之实例方法引用
-
语法
1 2
containingObject::instanceMethodName //实例:方法
-
System.out.println是谁
常用的System.out.prinln
中,System
是包java.lang
下的final类。out
则是该类中的标准输出流的静态变量。1
public static final PrintStream out = null;
通过
System.out
可以获得一个PrintStream实例。println
正是该PrintStream类中的方法,它接受一个String参数,返回void:1
public void println(String x) {...}
那么作为返回类型的
Outputter
是什么呢?是一个接口,有且只有一个抽象方法,因此是一个函数式接口。 -
从匿名函数到lambda再到方法引用
将接口的实现赋值给接口类型的变量,在java8之前,我们可以用匿名函数来实现:1 2 3 4 5 6
Outputter outputter = new Outputter() { @Override public void output(String input) { System.out.println(input); } };
java8推出lambda表达式以后,就可以将代码简化成lambda表达式:
1
Outputter outputter = input -> System.out.println(input);
箭头前是参数,箭头后是对参数的执行代码块。
将上述表达式再简化一点,就可以写成方法引用的形式:
1
Outputter outputter = System.out::println;
以上几种写法本质上都是相同的,都是对函数式接口进行了匿名实现,将其赋值给接口类型的变量。
现在再回到开头的Dagger示例就可以很快反应过来,return中的方法引用表达式,确实可以获得Outputter类型的返回值。