我的通用型铸件出了什么问题?

时间:2012-05-11 01:22:26

标签: java generics

我有一个Student类和一个StudentPool类定义如下:

public class Student {
    public Student copy () {
        return new Student();
    } 
}

public class StudentPool<T extends Student> {
    public T copyStudent(T t) {
        return t.copy();
    }
}

因此,copyStudent方法无法编译,我必须使用非安全类型转换。我不明白为什么Java认为这是非法的?

修改 user845279,lcfseth和Bohemian:我认为以下对Student的修订可能会导致类似的情况,将父类强制转换为其子类,但此版本可以通过编译:

public class Student {
    public <T extends Student> T copy() {
       T rv = null; 
       return rv;
    } 
}

修改 忘记上面的代码:rv可以是null,也可以是不安全的。

3 个答案:

答案 0 :(得分:4)

假设您有一个SmartStudent扩展StudentStudentPool<SmartStudent>的课程copyStudent。在这种情况下,SmartStudent应该使用SmartStudent并返回Student,但Student中的实现不会执行此操作 - 它只返回普通Student实例

修改

为了实现您想要的模式,您可以将public class Student { public Student(Student other) { //copy other's Student fields to this instance } } public class SmartStudent extends Student { public SmartStudent(SmartStudent other) { super(other); //copy other's SmartStudent fields to this instance } } 及其所有子类设为copy constructor

StudentPool

并使public abstract class AbstractStudentPool<T extends Student> { public T copyStudent(T original); } 抽象:

AbstractStudentPool

每个public class SmartStudentPool extends AbstractStudentPool<SmartStudent> { @Override public SmartStudent copyStudent(SmartStudent original) { return new SmartStudent(original); } } 实现都会调用相应的复制构造函数:

{{1}}

答案 1 :(得分:2)

问题在于虽然StudentStudent返回copy(),但子类返回Student ...而不是他们自己的类型。

这是解决问题的方法:

public static interface Copyable<T> {
    public T copy();
}

public static class Student implements Copyable<Student> {
    @Override
    public Student copy() {
        return new Student();
    }
}

public static class StudentPool<T extends Student> {
    public T copyStudent(Copyable<T> t) {
        return t.copy();
    }
}

作为旁注,似乎你不需要这里的泛型。

答案 2 :(得分:0)

您不能将父类强制转换为其子类。隐式演员只是相反的方式。即使使用显式类型转换,这也很可能会产生运行时错误。