CoreJava 中说到Supplier<T>实现了懒计算. 那懒计算和普通计算有什么区别? Supplier<T>和普通懒计算有什么区别?
懒计算和普通计算的区别(一切都在注释里了)
public class Difference{
public static void main(String... args){
/*
正常的计算方式:
方法指定形参, 按照形参将对应实参传递进去
*/
mth1(new Object());
/*
懒计算方式:
方法指定了形参, 但是方法中不一定真的需要对应实参对象. 例如mth(obj)的方法体可能中有根据状态而判定不需要调用obj.
依照运算符执行顺序, 方法执行前肯定会执行返回实参的方法以生成. 如果将产生实参的方法包装到对象中, 在需要实参时调用对象的方法生成实参. 可避免不需要实参而生成实参的资源浪费.
下面的这个例子需要一个Object类型的实参. 避免Object对象的浪费, 但需要一个Factory对象. 好像捡了芝麻丢了西瓜. 但假如需要一个包含很多数据的对象时, 节约一个创建实参的资源量就可以忽略Factory的创建了.
*/
mth2(new Factory());
}
public static void mth1(Object obj){
}
public static void mth2(Factory fac){
fac.create();
}
}
public class Factory{
public Object create(){
return new Object();
}
}
Supplier<T> 和普通懒计算的区别
普通懒计算如上所示: 为了避免new 一个体量大的对象而增加一个class. 如果使用lambda 中Supplier<T> 可以直接使用一条语句完场上述任务
public class Difference{
public static void main(String... args){
// 使用Supplier<T> 对应的lambda 表达式
mth3(()-> new Object());
// 使用Supplier对应的方法引用可以更减轻手指的负担
mth3(Object::new);
}
public static void mth3(Supplier\<Object\> supp){
supp.get();
}
}
"面向对象"者的不满足
为了增强Factory 方法的通用性, 可以面向接口编程. 这也刚好满足面向对象的"针对接口编程, 而不针对实现编程"的设计原则.
public interface Factory{
Object create();
}
public class FactoryImp implements Factory{
Object create(){
return new Object();
}
}
总结
Lambda 中Supplier完美的结合了上面提到的"针对接口编程而不针对实现编程", 有方法专门创建对象(设计模式中的工厂模式), 还有上面偶尔提到的泛型编程. Lambda 中定义了很多类似Supplier 的函数式接口, 不仅完成了懒计算, 还让手指头理直气壮地懒着不动.