关于Java中lambda的懒计算

1,167 阅读2分钟

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 的函数式接口, 不仅完成了懒计算, 还让手指头理直气壮地懒着不动.