Java 用于获取和调用具有泛型父级的子级的方法的编程返回类型或强制转换 -项目类-
A类:Java 用于获取和调用具有泛型父级的子级的方法的编程返回类型或强制转换 -项目类-,java,generics,casting,abstract-class,Java,Generics,Casting,Abstract Class,A类: 公共A类{ 公共静态void main(字符串[]args){ D=新的D(); B.set(d); d、 添加(新H());//$(更正错误) B.get().add(新的H());/!(无错误) } } B类: 公共B类{ 保护静电; 公共静态C get(){ 返回B.c; } 公共静态无效集(C) B.c=c; } C类: 公共抽象类C{ 受保护的ArrayList数组=新的ArrayList(); 公共无效添加(T元素){ this.array.add(元素); } } D
公共A类{
公共静态void main(字符串[]args){
D=新的D();
B.set(d);
d、 添加(新H());//$(更正错误)
B.get().add(新的H());/!(无错误)
}
}
B类:
公共B类{
保护静电;
公共静态C get(){
返回B.c;
}
公共静态无效集(C)
B.c=c;
}
C类:
公共抽象类C{
受保护的ArrayList数组=新的ArrayList();
公共无效添加(T元素){
this.array.add(元素);
}
}
D类:
公共类D扩展了C{
//
}
E类:
公共类E扩展了C{
//
}
F类:
公共抽象类F{
//
}
G类:
公共类G扩展了F{
//
}
H类:
公共类H扩展了F{
//
}
-班级角色-
A
是主类B
是存储对象引用的类C
是定义对象数组的通用类D
和E
使用不同类型扩展C
G
和H
使用不同类型扩展F
A.main()代码>表示问题所在的位置,/$
表示所需的行为。由于B.get()
返回抽象类型C
,因此可以将非法元素添加到array
中(在本例中,由于D
对C
的扩展,只有G
是合法的,所以添加H
)
程序中不知道从B.get()
返回的对象的类型(因为B.c
可以表示D
或E
类型的对象),因此对B
进行修改以检查c
的类型并返回它或在B.get()的调用中自动强制转换它是理想的,如果可能的话
-问题编辑-
为了澄清,使用((D)B.get()).add(new H())进行转换代码>没有帮助,因为B.c持有的子类型未知。如果可以执行类似于((B.get().getClass())B.get()).add(new H())
)的操作,那将非常有用。如果可能的话,我选择的解决方案最好是改变方法B.get()
,而不是改变主方法
为了进一步澄清,解决此问题的结果应导致错误,以防止在从B.get()
引用时向数组添加非法类型(/!
表示没有错误发生的位置,/$
表示错误发生的位置)。我愿意重新编写如何在B
中保存对D
和E
实例的引用,前提是可以实现对C
类型的动态引用(typeD
或typeE
)。听起来好像你在试图让泛型做动态类型安全,这是他们因为擦除而做得很糟糕的事情。使用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> {
//
}
公共A类{
公共静态void main(字符串[]args){
D=新的D();
B.put(G级,d级);
B.get(H.class).add(new H());//动态类型,但在编写时易受null的影响
d、 添加(新G());//$(不再导致错误)
}
}
公共B级{
受保护的静态映射mapC;
公共静态C get(类clsT){
返回(C)mapC.get(clsT);
}
公开静态无效认沽权(类别clsT,C){
mapC.put(clsT,c);
}
}
公共抽象类C{
受保护的ArrayList数组=新的ArrayList();
公共void添加(类型元素){
this.array.add(元素);
}
}
公共类D扩展C{
//
}
公共类E扩展C{
//
}
公共抽象类F{
//
}
公共类G扩展F{
//
}
公共类H扩展F{
//
}
当您将C
作为没有类型参数的B
中静态字段的类型时,您的程序总是会有危险的潜在类型错误。D
应该与G
s而不是H
s一起工作。基本上是“什么是原始类型,为什么我们不应该使用它?”的精心复制