Java 通用字段声明

Java generic field declaration

在没有通用类型的 class 中,我想声明一个相当复杂的通用字段,类似于这些:

public class Client {
    private Map<Class<T extends Serializable>, List<Consumer<S extends T>>> classToConsumerTry1;

    private <T extends Serializable, S extends T> Map<Class<T>, List<Consumer<S>>> classToConsumerTry2;
}

问题是 java 编译器不允许我:)

所以我的问题是如何在不向 class 客户端添加类型的情况下正确引入 T 和 S。

我的目标是强制 Class 成为 Serializable 的子类型,Consumer 成为您为 Class 选择的 class 的子类型.

你不能。您唯一的选择是在 Client class 声明中声明泛型类型参数。如果你的 Client class 没有泛型类型参数,它的成员就不能是泛型的。您必须在 class 成员的声明中使用实际类型。

您必须在某处引入类型参数,以便您可以在 class 成员的定义中使用它们。

只能在 class 级或方法级引入类型参数。在您的情况下,它应该在 class 级别:

public class Client<T extends Serializable, S extends T> {
    private Map<Class<T>, List<Consumer<S>>> classToConsumerTry1;

    private Map<Class<T>, List<Consumer<S>>> classToConsumerTry2;
}

然而,这意味着对于两个成员(classToConsumerTry1classToConsumerTry2),TS 是相同的。如果您希望它们不同,则必须从两个不同的 classes 中获取这两个值,这两个值都使用单独的类型参数进行参数化。

你不能直接在现场做,但你可以通过泛型方法维护你的类型策略(它们甚至可以存在于非泛型中class):

@SuppressWarnings("rawtypes")
private Map<Class, List> map;

public <T extends Serializable> void put(Class<T> key, List<Consumer<? extends T>> value) {
    map.put(key, value);
}

@SuppressWarnings("unchecked")
public <T extends Serializable> List<Consumer<? extends T>> get(Class<T> key) {
    return map.get(key);
}

你不能按照你想要的方式完成。但您可以设置为 Object 并投射。其他 hacky 答案包括使用 List of <? extends Serializable>(但这只适用于一个 extends),然后 add() 你的项目或内部 class 做某事喜欢:

private class Foo<T> {
        T obj;
}

因此您可以在内部 access/mutate obj

请注意,可以将 class 类型声明为字段(因为 google 派我来这里询问这个不相关的问题...)

  Class<? extends MyInterface> myCurrentClass = MyImplementation.class;