我有一个带有两个(重载)方法的接口的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目标,并在所有实现类中实现它。这看起来有点草率/不需要......还有其他任何建议吗?
答案 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
。