我有一个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
,也可以是不安全的。
答案 0 :(得分:4)
假设您有一个SmartStudent
扩展Student
和StudentPool<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)
问题在于虽然Student
从Student
返回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)
您不能将父类强制转换为其子类。隐式演员只是相反的方式。即使使用显式类型转换,这也很可能会产生运行时错误。