如何实现泛型方法遍历Student子类对象并打印详情
好的,我来帮你解决这个问题。要实现你想要的效果,我们可以从两个方面入手:限定泛型的类型范围(确保只能接收Student的子类列表),以及优雅地打印对象详情。下面分步骤说明:
首先,改造showDetails方法,把原来的List<?>改成List<? extends Student>——这样就明确限定了列表中的元素必须是Student的子类,既保留了灵活性,又能安全地调用Student类的公共方法(比如getStid()),不用再处理Object类型的强转问题。
接下来是打印详情的部分,有两种常用方案,推荐优先用第一种:
方案1:重写toString()方法(推荐,符合OOP设计)
在Student及其子类中重写toString(),这样遍历列表时直接打印对象就能输出所有属性,代码更简洁,也符合开闭原则(后续新增Student子类时,只需要重写自己的toString,不用修改showDetails方法)。
修改后的完整代码如下:
import java.util.ArrayList; import java.util.List; class Student{ private int stid; public int getStid() { return stid; } public void setStid(int stid) { this.stid = stid; } @Override public String toString() { return "Student{stid=" + stid + "}"; } } class Details extends Student{ private String name; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Details{" + "stid=" + getStid() + ", name='" + name + '\'' + ", address='" + address + '\'' + '}'; } } class Course extends Student{ private String shortTerm; private String fullTerm; public String getShortTerm() { return shortTerm; } public void setShortTerm(String shortTerm) { this.shortTerm = shortTerm; } public String getFullTerm() { return fullTerm; } public void setFullTerm(String fullTerm) { this.fullTerm = fullTerm; } @Override public String toString() { return "Course{" + "stid=" + getStid() + ", shortTerm='" + shortTerm + '\'' + ", fullTerm='" + fullTerm + '\'' + '}'; } } public class Test { // 改造后的方法:限定为Student子类的列表 void showDetails(List<? extends Student> obj) { System.out.println("=== 列表详情 ==="); for(Student ob : obj) { // 直接打印对象,会调用对应子类的toString() System.out.println(ob); } } public static void main(String[] args) { Details d1 = new Details(); d1.setName("John"); d1.setAddress("Street 21"); d1.setStid(10); Details d2 = new Details(); d2.setName("Sam"); d2.setAddress("Street 151"); d2.setStid(11); List<Details> listObj = new ArrayList<>(); listObj.add(d1); listObj.add(d2); new Test().showDetails(listObj); // course Course c1 = new Course(); c1.setShortTerm("6months"); c1.setFullTerm("12 months"); c1.setStid(111); List<Course> courseList = new ArrayList<>(); courseList.add(c1); new Test().showDetails(courseList); } }
运行后输出:
=== 列表详情 === Details{stid=10, name='John', address='Street 21'} Details{stid=11, name='Sam', address='Street 151'} === 列表详情 === Course{stid=111, shortTerm='6months', fullTerm='12 months'}
方案2:通过instanceof判断类型并打印
如果不想重写toString,可以在showDetails方法中判断对象的具体类型,强转后打印属性。这种方式适合需要自定义打印格式的场景,但后续新增子类时需要修改showDetails方法,扩展性稍差:
修改后的showDetails方法:
void showDetails(List<? extends Student> obj) { System.out.println("=== 列表详情 ==="); for(Student ob : obj) { System.out.println("学生ID:" + ob.getStid()); if (ob instanceof Details) { Details details = (Details) ob; System.out.println("姓名:" + details.getName()); System.out.println("地址:" + details.getAddress()); } else if (ob instanceof Course) { Course course = (Course) ob; System.out.println("短期课程:" + course.getShortTerm()); System.out.println("长期课程:" + course.getFullTerm()); } System.out.println("---"); } }
运行后输出:
=== 列表详情 === 学生ID:10 姓名:John 地址:Street 21 --- 学生ID:11 姓名:Sam 地址:Street 151 --- === 列表详情 === 学生ID:111 短期课程:6months 长期课程:12 months ---
最后补充一点:你也可以把showDetails写成泛型方法的形式,效果和用通配符<? extends Student>是一样的,比如:
<T extends Student> void showDetails(List<T> obj) { // 内部实现和上面一致 }
两种写法都能达到你的需求,选哪种看个人习惯~
内容的提问来源于stack exchange,提问作者user222
相关产品推荐
相关产品推荐

