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;
}
然而,这意味着对于两个成员(classToConsumerTry1
和 classToConsumerTry2
),T
和 S
是相同的。如果您希望它们不同,则必须从两个不同的 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;
在没有通用类型的 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;
}
然而,这意味着对于两个成员(classToConsumerTry1
和 classToConsumerTry2
),T
和 S
是相同的。如果您希望它们不同,则必须从两个不同的 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;