Java通用转换不符合预期

时间:2013-02-20 15:43:33

标签: java generics type-conversion

如果有人可以为我解决这个难题。我相信我错过了什么!

interface a { }
class b implements a { }
class c extends ArrayList<b> { }
class d {
    d(ArrayList<a> param) {}
}

class e {
    public static void main(String[] arg) {
         d newd = new d(new c());
    }
}

此代码有错误: 错误d(ArrayList<a>) is not applicable (actual argument c cannot be converted to ArrayList<a> by method invocation conversion)

c扩展ArrayList<a>c实现ArrayList<b>时,类b肯定可以转换为a! 我尝试过显式转换,但没有帮助。

class c extends ArrayList<b>改为extends ArrayList<a>作为c的集合b和接口a的目的是没有意义的仅用于显示目的。类d也是一个通用的显示类,它依赖于接口a中表达的功能,所以改变它也没有意义。

建议会很方便!

4 个答案:

答案 0 :(得分:3)

这应该符合您的需求:

class d {
    d(ArrayList<? extends a> param) {
    }
}

c不是ArrayList<a>,而是ArrayList<? extends a>,因为ba的子类型。

答案 1 :(得分:0)

问题是ArrayList与ArrayList不同,即使b扩展A.如果D调用param.add(new AImpl()),其中AImpl是接口A的其他实现,会发生什么?

有关详细信息,请参阅The Java Generics Tutorial section on inheritance

(顺便说一句,扩展一个ArrayList通常也不是一个好主意 - 大部分时间,你想要包装它,而不是扩展它。)

答案 2 :(得分:0)

应该是:

d(ArrayList<? extends a> param) {}

ArrayList不是ArrayList的子类,因为前者可以添加一个,而后者则不能。

答案 3 :(得分:0)

请尊重java命名约定:

interface A {
}

class B implements A {
}

class C extends ArrayList<B> {
}

class D {

    D(ArrayList<A> param) {
    }
}

class E {

    public static void main(String[] arg) {
        D newd = new D(new C());
    }
}

因此,您的假设是ArrayList<B>可以投放到ArrayList<A> B implements A。这不是真的,这不是泛型如何工作。你根本无法转换泛型类型。 尝试做类似的事情:

final ArrayList<Object> myNewArrayList = new ArrayList<String>();

提炼问题。
您需要使用bounded type parameters来解决此问题。将您的D课程更改为:

class D {

    D(ArrayList<? extends A> param) {        
    }
}

现在你会说:我想要一个任何类型的集合,只要它是A