如何阻止功能接口成为lambda表达式的目标?

时间:2017-08-20 02:49:22

标签: java lambda functional-interface

我有一个带有两个(重载)方法的接口的API,它们采用不同的参数类型。这些不同类型都是技术上功能的接口,但不应允许用户创建其中一个的实例。这是一个简化的例子:

public class Example
{
    @FunctionalInterface
    public interface Computation
    {
        int compute();
    }

    public interface WrappedComputation
    {
        Computation unwrap();
    }

    public static class Solver
    {
        public static int solve(Computation a)
        {
            return a.compute();
        }

        public static int solve(WrappedComputation b)
        {
            return solve(b.unwrap());
        }
    }

    public static void main(String... args)
    {
        // 'Computation' interface should be a lambda target
        // so coder can make their own 'A' computation
        Solver.solve( () -> { return 5 + 5; } );

        // 'WrappedComputation' interface SHOULD NOT be a lambda target
        // or else coder can cause runtime exceptions etc., like passing a null 'Computation' reference that will be computed
        Solver.solve( () -> { Computation a = null; return a; } );
    }
}

我到目前为止唯一的想法是在接口上添加一个虚拟/未使用的方法,我不想成为一个lambda目标,并在所有实现类中实现它。这看起来有点草率/不需要......还有其他任何建议吗?

2 个答案:

答案 0 :(得分:3)

当您的界面满足the criteria时,无法阻止API客户端使用lambda表达式。

您认为API客户端通过lambdas导致问题的假设是错误的 - 您可以使用lambda做任何坏事,您也可以使用匿名内部类或命名类。考虑:

Solver.solve( new WrappedComputation(){
    public Computation unwrap(){
        Computation a = null; return a;
    }
});

这与lambda具有完全相同的语义和最终结果(运行时异常)。

或许您想要的是阻止任何不受控制地创建WrappedComputation?在这种情况下,请考虑将其设置为final class,其构造函数检查错误情况:

public final class WrappedComputation{
    private final Computation _wrapped;
    public WrappedComputation(@NonNull wrapped){
        _wrapped = Objects.requireNonNull(wrapped);
    }
}

答案 1 :(得分:2)

编码器总是会导致运行时异常,因此这是一个错误的借口。

如果你不想模棱两可,不要超载这个方法 将其命名为其他内容,例如solveWrapped