泛型使用:如何编写支持父类泛型引用的Registration泛型类声明
嘿,我来帮你搞定这个泛型类的问题!首先咱们得理清核心需求:你想要一个能存储任意类型T的泛型类Registration,同时希望能把Registration<Student>的实例赋值给Registration<Person>的引用——这里得先纠正一个小误区,Java里泛型默认是不可变的,也就是说Registration<Person>和Registration<Student>之间没有继承关系,直接赋值会编译报错。不过咱们可以通过通配符或者调整类的设计来实现类似的效果,同时满足你支持String、Person、Student等多种类型的需求。
第一步:正确的Registration泛型类声明
先写基础的泛型类,这个类可以存储任意类型的T对象,支持你需要的多种类型实例化:
public class Registration<T> { // 存储T类型的变量 private T data; // 无参构造,匹配你例子里的实例化方式 public Registration() {} // 带初始数据的构造方法 public Registration(T data) { this.data = data; } // 获取存储的数据 public T getData() { return data; } // 设置存储的数据 public void setData(T data) { this.data = data; } }
这个类的泛型声明Registration<T>是标准写法,T作为类型参数,可以替换为任意引用类型(String、Person、Student都没问题)。
第二步:处理你想要的Registration<Person> r2 = new Registration<Student>()需求
刚才说了,直接这么写编译会报错,因为泛型不可变。那怎么实现类似的“父类型引用指向子类泛型实例”的效果呢?有两种实用方案:
方案1:使用通配符? extends T调整引用类型
把引用类型改成Registration<? extends Person>,这样就能接受任何Person子类的Registration实例了:
// 合法!? extends Person表示可以接受Person或其任意子类的Registration实例 Registration<? extends Person> r2 = new Registration<Student>();
这种方式的好处是完全不修改类的结构,同时兼容你对String类型的需求:
// 依然正常工作 Registration<String> r1 = new Registration<String>();
方案2:如果你的场景只需要处理Person及其子类
如果你这个Registration类大部分时候是用来处理Person体系的对象,也可以在类声明时给T加上上界限制:
// T必须是Person或其子类 public class Registration<T extends Person> { private T data; // 构造方法、get/set方法和上面一致 }
但这种写法的问题是不能再用String类型实例化了,所以如果需要支持String的话,方案1更合适。
验证一下效果
用方案1的话,所有需求都能满足:
// 实例化String类型的Registration Registration<String> r1 = new Registration<String>(); r1.setData("Alice"); System.out.println(r1.getData()); // 输出Alice // 实例化Student类型的Registration,赋值给Person通配符的引用 Registration<? extends Person> r2 = new Registration<Student>(); // 注意:使用? extends时,不能调用set方法(编译器不知道具体是哪个子类),只能调用get方法 Person person = r2.getData();
这样就完美解决你的问题啦!
内容的提问来源于stack exchange,提问作者R83nLK82

