【发布时间】:2016-02-12 00:30:31
【问题描述】:
一些背景
我正在开发一个基于 Lambda 表达式的小型 DI 容器。 我有代表 lambda 的接口:
@FunctionalInterface
public interface LambdaOp<T> {
T resolve();
}
这是(非常简化的)容器:
public class Container {
private final Map<Class<?>, LambdaOp<?>> bindings;
public <T> void bind(Class<T> clazz, LambdaOp<? extends T> lambda) {
bindingd.put(clazz, lambda);
}
public <T> T resolve (Class<T> clazz) {
LambdaOp<?> lambda = bindings.get(clazz);
return (T) lambda.resolve();
}
}
有了这个实现,我可以做这样的事情:
container.bind(
FooInterface.class,
() -> {
FooImplementation foo = new FooImplementation();
foo.setParameterA(paramA);
//do whatever needed to configure it
return foo;
}
);
FooInterface foo2 = container.resolve(FooInterface.class);
它工作正常而且很好,因为编译器不会让我做这样的事情:
container.bind(
FooInterface.class,
() -> new BarImplementation() //compiler error; Bar does not implement Foo
);
问题
绑定 Map 本身并不保证 LambdaOp 会有一个泛型类型,该类型扩展了用作键的类。
private final Map<Class<?>, LambdaOp<?>> bindings;
因此,我在以下行收到未经检查的警告:
return (T) lambda.resolve();
我认为绑定方法签名足以保证内聚(是吗?)但仍然感觉有些难闻。
有没有什么方法可以以更有凝聚力的方式实现它?
编辑:
完整代码位于github。我最近做了很多改动,README.md very有点过时了。
【问题讨论】:
-
据我所知,没有办法解决这个问题。我不会认为警告是一个问题,因为它隐藏在您的实施背后。将始终保证客户端接收到正确的类型,因为(如您所述)添加到地图的唯一方法是通过您的
bind方法。 -
在 Java 中,任何时候转换为不可具体化的泛型类型,都会收到未经检查的警告。这是因为类型信息在运行时不存在,Java 环境无法保证强制转换的类型安全。这样的情况无济于事..如果您分析自己的代码并且可以证明它是类型安全的,那么只需取消警告。
-
不错。我使用这个项目作为学习语言的工具,从更有经验的开发人员那里得到一些反馈总是好的。
-
顺便说一句,您的
LambdaOp<T>接口可以替换为标准Supplier<T>
标签: java generics lambda java-8