Java 和泛型类型边界

标签 java generics lambda java-8

<分区>

一些背景

我正在开发一个基于 Lambda 表达式的小型 DI 容器。 我有代表 lambda 的接口(interface):

@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
);

问题

绑定(bind) Map 本身不保证 LambdaOp 将具有扩展用作键的类的泛型。

private final Map<Class<?>, LambdaOp<?>> bindings;

因此,我在以下行收到了一个未经检查的警告:

return (T) lambda.resolve();

我想 bind 方法签名足以保证内聚性(是吗?)但仍然感觉有些难闻。

有没有办法以更统一的方式实现它?

编辑:

完整代码在github .我最近做了很多更改,README.md 非常有点过时了。

最佳答案

为什么不直接使用 Class clazz 键进行转换?您的逻辑已经保证转换将始终有效

return clazz.cast( lambda.resolve() );

编辑澄清: 使用 Class 对象在没有警告的情况下工作但简单泛型转换没有的原因是因为在运行时使用泛型转换,泛型类型也可能被删除为 Object 因此编译器无法保证转换将适用于预期类型。另一方面,Class 对象将具有执行转换所需的所有信息,因此编译器可以安全地允许它用于泛型类型。

当然,假设您没有特意去搞乱泛型。

关于Java 和泛型类型边界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35352748/

相关文章:

java - 是否可以创建具有最小和最大范围的浮点类型?

delphi - 使用泛型类型数组的类成员调整类实例大小

mysql - AWS Lambda 不执行 node.js MySQL 查询

Java 类型转换问题

java - 如何使用 Java 8/lambda 执行嵌套的 'if' 语句?

c# - 如何在 C# 中的 lambda 表达式中查找数组中元素的索引

java - 场景生成器,如何配对 ComboBoxs 选择

java - 使用 java generic 从 java 调用重载的 scala case apply

java - 如何每秒移动 jlabel?

Java:对具有两种类型的泛型类进行排序