![](/img/trans.png)
[英]Overwriting the List type of the parent class to avoid casting when calling methods
[英]Programmatic return type or casting for getting, and calling methods of, a child with a generic parent
A类:
public class A {
public static void main(String[] args) {
D d = new D();
B.set(d);
d.add(new H()); //$ (correct error)
B.get().add(new H()); //! (no error)
}
}
B类:
public class B {
protected static C c;
public static C get() {
return B.c;
}
public static void set(C c)
B.c = c;
}
C类:
public abstract class C<T> {
protected ArrayList<T> array = new ArrayList<T>();
public void add(T element) {
this.array.add(element);
}
}
D类:
public class D extends C<G> {
//
}
E级:
public class E extends C<H> {
//
}
F级:
public abstract class F<T> {
//
}
G类:
public class G extends F<X> {
//
}
H类:
public class H extends F<Y> {
//
}
A
是主类B
是一个存储对象引用的类C
是定义对象数组的泛型类D
& E
用不同的类型扩展C
G
& H
用不同的类型扩展F
在A.main()
, //!
表示问题所在, //$
表示所需的行为。 因为B.get()
返回抽象类型C
,所以可以向array
添加非法元素(在本例中,由于D
对C
的扩展,当只有G
合法时添加H
)。
从B.get()
返回的对象的类型在程序中是未知的(因为Bc
可以表示类型D
或类型E
的对象),因此修改B
以检查c
的类型并返回它或自动返回如果可能的话,在B.get()
的调用中投射它是理想的。
为了澄清((D) B.get()).add(new H());
,使用((D) B.get()).add(new H());
没有帮助,因为 Bc 持有的孩子类型是未知的。 如果可以做类似于((B.get().getClass()) B.get()).add(new H())
事情,那会很有帮助。 如果可能的话,我会选择的解决方案最好是更改或更改方法B.get()
而不是主要方法。
为了进一步澄清,解决此问题的结果应该会导致错误,以防止在从B.get()
引用时向数组中添加非法类型( //!
表示没有错误发生的位置, //$
表示在错误应该发生)。 如果可以完成引用C
类型(类型D
或类型E
)的动态方式,我愿意重写如何在B
保存对D
和E
实例的引用。
泛型类型仅在编译时有效。 听起来您正试图让泛型具有动态类型安全性,这是由于擦除而它们在做的事情上很糟糕。 将B
用作静态c
具有不断变化类型的单例是非常尴尬的。 您可以尝试在 B 中保留从Class<?>
到C<?>
的映射,并在尝试调用add
之前获取适当的映射,我猜。
另外,在//$
您只是使用了错误的子类。
d.add(new G());
类型检查正确。
这就是我的意思:
public class A {
public static void main(String[] args) {
D d = new D();
B.put( G.class, d);
B.get( H.class ).add(new H()); // dynamic typing, but susceptible to null as written
d.add(new G()); //$ (no longer causes error)
}
}
public class B {
protected static Map< Class<?>, C<?> > mapC;
public static <T> C<T> get( Class<T> clsT ) {
return ( C< T > )mapC.get( clsT );
}
public static < T > void put(Class< T > clsT, C<T> c) {
mapC.put( clsT, c );
}
}
public abstract class C<Type> {
protected ArrayList<Type> array = new ArrayList<Type>();
public void add(Type element) {
this.array.add(element);
}
}
public class D extends C<G> {
//
}
public class E extends C<H> {
//
}
public abstract class F<Type> {
//
}
public class G extends F<String> {
//
}
public class H extends F<Integer> {
//
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.