繁体   English   中英

用于获取和调用具有通用父级的子级的编程返回类型或强制转换

[英]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> {
    //
}

-班级角色-

  1. A是主类
  2. B是一个存储对象引用的类
  3. C是定义对象数组的泛型类
  4. D & E用不同的类型扩展C
  5. G & H用不同的类型扩展F

-逻辑问题-

A.main()//! 表示问题所在, //$表示所需的行为。 因为B.get()返回抽象类型C ,所以可以向array添加非法元素(在本例中,由于DC的扩展,当只有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保存对DE实例的引用。

泛型类型仅在编译时有效。 听起来您正试图让泛型具有动态类型安全性,这是由于擦除而它们在做的事情上很糟糕。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM