我长期以来一直在Java中使用一种习惯用法,在其(通常是抽象的)祖先类的方法中使用(非抽象)类的类信息(不幸的是,我找不到此模式的名称):
public abstract class Abstract<T extends Abstract<T>> {
private final Class<T> subClass;
protected Abstract(Class<T> subClass) {
this.subClass = subClass;
}
protected T getSomethingElseWithSameType() {
....
}
}
其子类的一个示例:
public class NonGeneric extends Abstract<NonGeneric> {
public NonGeneric() {
super(NonGeneric.class);
}
}
但是,我在定义其子类Abstract
具有自己的通用参数时遇到了麻烦:
public class Generic<T> extends Abstract<Generic<T>> {
public Generic() {
super(Generic.class);
}
}
这个例子是不可编译的。同样,不可能使用例如eg来指定通用类型Generic<T>.class
,甚至不能使用Generic<?>
。
我还尝试将超类T
中的泛型类型声明替换为? extends T
,但这也不可编译。
有什么办法可以使这种模式与通用基类一起使用?
传递Class<T>
(通常传递给构造函数的)实例的“模式”(惯用语)使用Class Literals作为Runtime-Type Tokens,并用于保留对泛型类型的运行时引用,否则将对其进行擦除。
解决方案是首先将令牌类更改为绑定到:
Class<? extends T>
然后对通用子类提出与超级类类似的要求;让具体类传递类型标记,但是您可以将其正确地作为参数输入:
这些类无需强制转换或警告即可编译:
public abstract class Abstract<T extends Abstract<T>> {
private final Class<? extends T> subClass;
protected Abstract(Class<? extends T> subClass) {
this.subClass = subClass;
}
}
public class NonGeneric extends Abstract<NonGeneric> {
public NonGeneric() {
super(NonGeneric.class);
}
}
public class Generic<T> extends Abstract<Generic<T>> {
public Generic(Class<? extends Generic<T>> clazz) {
super(clazz);
}
}
最后,在具体的类中,如果您将用法声明为自己的类,则不需要在任何地方进行强制转换:
public class IntegerGeneric extends Generic<Integer> {
public IntegerGeneric() {
super(IntegerGeneric.class);
}
}
我还没有弄清楚如何在没有强制转换的情况下创建Generic
(匿名或非匿名)实例:
// can someone fill in the parameters without a cast?
new Generic<Integer>(???); // typed direct instance
new Generic<Integer>(???) { }; // anonymous
我认为这是不可能的,但我欢迎其他方式的出现。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句