You need to enable JavaScript to run this app. Java实现:如何将父子类字段值共同存入LibraryItem类型的ArrayList
优惠活动
大模型
产品
解决方案
定价
更多

Java实现:如何将父子类字段值共同存入LibraryItem类型的ArrayList

代码现存硬伤点
  • 分隔符规则冲突:子类readData里把分隔符设为[,\n],父类readData又改成\\s?,\\s?,两套规则切换时很容易出现切分错位,触发NoSuchElementException
  • 冗余代码无效:Library类的分支里提前给Scanner设置的分隔符,进到子类readData后会被覆盖,完全是无意义的重复操作
  • 字段解析错位风险:当前父类、子类的读字段顺序,需要和CSV文件的列顺序严格对齐,一旦列顺序写错,会直接导致类型转换报错、字段值张冠李戴
  • 有参构造赋值漏失:Book类的带参构造接收了noOfPages、publisher两个父类字段值,但没有传给父类做赋值,走该构造路径时父类字段全是默认初始值
完整可运行的实现方案

1. 全局统一分隔符规则

把分隔符的设置逻辑前置到Library类创建Scanner的位置,只设置一次就全链路生效,所有readData方法里删掉重复的分隔符代码。
注意:必须用兼容逗号前后带空格的正则\\s*,\\s*,适配大部分CSV导出的格式
修改后的分支代码:

if (typeOfData.equals("Book")) {
    System.out.println(lineOfText);
    Scanner scanner2 = new Scanner(lineOfText);
    // 一次设置,后续读数据全程生效
    scanner2.useDelimiter("\\s*,\\s*");
    LibraryItem libraryItem = new Book();
    libraryItem.readData(scanner2);
    storeItem(libraryItem);
    scanner2.close();
} else if (typeOfData.equals("Periodical")) {
    System.out.println(lineOfText);
    Scanner scanner2 = new Scanner(lineOfText);
    scanner2.useDelimiter("\\s*,\\s*");
    LibraryItem libraryItem = new Periodical();
    libraryItem.readData(scanner2);
    storeItem(libraryItem);
    scanner2.close();
}

2. 对齐解析顺序

严格按照「子类独有字段在前、父类公共字段在后」的逻辑写readData方法,保证和CSV列顺序完全匹配:

  • 父类LibraryItem的readData方法删掉分隔符设置,按固定顺序读公共字段即可:
public void readData(Scanner scanner2) {
    this.noOfPages = scanner2.nextInt();
    this.publisher = scanner2.next().trim();
    this.title = scanner2.next().trim();
    this.itemCode = scanner2.next().trim();
    this.cost = scanner2.nextInt();
    this.timesBorrowed = scanner2.nextInt();
    this.onLoan = scanner2.nextBoolean();
}
  • Book类的readData方法,先读自身独有的author、isbn字段,再调用super读公共字段:
@Override
public void readData(Scanner scanner2) {
    this.author = scanner2.next().trim();
    this.isbn = scanner2.next().trim();
    super.readData(scanner2);
}
  • Periodical类的readData方法,先读自身独有的publicationDate字段,再调用super读公共字段:
@Override
public void readData(Scanner scanner2) {
    this.publicationDate = scanner2.next().trim();
    super.readData(scanner2);
}

注意:CSV文件里的列顺序必须和上面的读取顺序严格对应,比如Book行的列必须是「作者,ISBN,页数,出版社,书名,馆藏编号,成本,累计借阅次数,是否在借」,Periodical行的列必须是「出版日期,页数,出版社,书名,馆藏编号,成本,累计借阅次数,是否在借」,不然一定会读错

3. 补全构造的字段传递

给LibraryItem增加带所有公共字段的构造方法,修正子类构造漏传父类值的问题:

// LibraryItem 新增的全参构造
public LibraryItem(int noOfPages, String publisher, String title, String itemCode, int cost, int timesBorrowed, boolean onLoan) {
    this.noOfPages = noOfPages;
    this.publisher = publisher;
    this.title = title;
    this.itemCode = itemCode;
    this.cost = cost;
    this.timesBorrowed = timesBorrowed;
    this.onLoan = onLoan;
}

子类构造调用对应的super方法,把所有值正确传递:

// Book 修正后的构造
public Book(String author, String isbn, int noOfPages, String publisher, String title, String itemCode, int cost, int timesBorrowed, boolean onLoan) {
    super(noOfPages, publisher, title, itemCode, cost, timesBorrowed, onLoan);
    this.author = author;
    this.isbn = isbn;
}

// Periodical 修正后的构造
public Periodical(String publicationDate, int noOfPages, String publisher, String title, String itemCode, int cost, int timesBorrowed, boolean onLoan) {
    super(noOfPages, publisher, title, itemCode, cost, timesBorrowed, onLoan);
    this.publicationDate = publicationDate;
}

4. 增加基础容错

在Scanner读数据的外层加简单的异常捕获,遇到单条解析失败的行直接打印错误信息跳过,不要因为一行坏数据中断整个文件的读取流程。

内容的提问来源于stack exchange,提问作者The_Liner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.31 01:24:06