You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现泛型方法遍历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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:18:31