如果您无法修改基类,则实际上没有涉及泛型的方法。你可以做两件事。一,检查对象的运行时类型,如果是老师,则做一件事,如果不是,则做另一件事。
public class MyClass extends MyBase {
@Override public <T> Student assign(T object) {
Student student = new Student();
if (object instanceof Teacher) {
Teacher teacher = (Teacher) object;
student.setTeacherName(teacher.getName());
} else {
student.setTeacherName("unknown");
}
return student;
}
}
二,在 MyClass 中创建两个单独assign
的方法,一个覆盖基类中的泛型方法,以及一个仅将 Teacher 作为参数的非泛型方法。
public class MyClass extends MyBase {
@Override public <T> Student assign(T object) {
return new Student();
}
public Student assign(Teacher teacher) {
Student student = new Student();
student.setTeacherName(teacher.getName());
return student;
}
}
调用方法时,如果编译时类型为 Teacher,编译器会选择方法更具体的重载:
public class Main {
/**
* Gets a teacher but calls it an Object.
*
* @return an Object that happens to be a Teacher
*/
public static Object getTeacher() {
return new Teacher();
}
public static void main(String[] args) {
/** A Teacher, and is declared as such */
Teacher teacher = new Teacher();
/**
* Some Object, which just so happens to actually
* be a Teacher (but the compiler can't see that)
*/
Object something = getTeacher();
MyClass mc = new MyClass();
Student withTeacher = mc.assign(teacher);
Student withoutTeacher = mc.assign(something);
}
}
但是,我更喜欢修改 MyBase 的解决方案之一。
编辑添加:您实际上可以将第二个更具体assign
的方法声明为通用方法,如下所示:
public <T extends Teacher> Student assign(T object) {
Student student = new Student();
student.setTeacherName(object.getName());
return student;
}
但这实际上与上面的第二个示例相同。该方法不会覆盖基类中的方法,它仍然依赖于编译器在编译时选择更具体的重载,并且方法签名的擦除与第二个示例中的非泛型方法完全相同:
public Student assign(Teacher)
它只是看起来更像是基类中方法的覆盖,因为它有一个泛型类型变量,并且参数被命名object
而不是teacher
. 但是尝试@Override
在其上添加注释,编译器会告诉您它不会覆盖或实现超类型的方法。
而且你仍然有<T>
没有设置教师名称的通用方法,如果你有一个没有这样声明的教师对象,编译器会选择错误的重载,你会摸不着头脑想知道为什么,如果对象是教师,则不会为学生设置教师名称。