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

如何使用Java Stream仅处理指定Employee子类生成PayrollEntry避免转换异常

不可修改的类层级结构

Employee 类

public abstract class Employee extends Person {
    private final Manager manager;
    private final BigDecimal salary;
    
    protected Employee(String firstName, String surname, LocalDate birth_date, Manager _manager, BigDecimal _salary) {
        super(firstName, surname, birth_date);
        manager = _manager;
        salary = _salary;
        if (manager != null) {
            manager.getSubordinates().add(this);
        }
    }
    // 其余方法省略
}

Worker 类

public class Worker extends Employee {
    private final LocalDate employment_date;
    private BigDecimal bonus;
    
    public Worker(String firstName, String surname, LocalDate birth_date, Manager manager, BigDecimal salary,
                  LocalDate _employment_date, BigDecimal _bonus) {
        super(firstName, surname, birth_date, manager, salary);
        employment_date = _employment_date;
        bonus = _bonus;
    }
    // 其余方法省略
}

Manager 类

public final class Manager extends Worker {
    List<Employee> subordinates = new ArrayList<Employee>();
    
    public Manager(String firstName, String surname, LocalDate birth_date, Manager manager, BigDecimal salary,
                   LocalDate employment_date, BigDecimal bonus) {
        super(firstName, surname, birth_date, manager, salary, employment_date, bonus);
    }
    // 其余方法省略
}

Trainee 类

public class Trainee extends Employee {

    private final LocalDate start_date;
    private final short apprenticeship_length;
    
    public Trainee(String firstName, String surname, LocalDate birth_date, Manager manager, BigDecimal salary,
                   LocalDate _start_date, short _apprenticeship_length) {
        super(firstName, surname, birth_date, manager, salary);
        manager.getSubordinates().add(this);
        start_date = _start_date;
        apprenticeship_length = _apprenticeship_length;
    }
}

PayrollEntry 类

public final class PayrollEntry {

    private final Employee _employee;
    private final BigDecimal _salaryPlusBonus;
    
    public PayrollEntry(Employee employee, BigDecimal salary, BigDecimal bonus) {
        _employee = employee;
        _salaryPlusBonus = salary.add(bonus);
    }
}
需求说明

实现函数 List<PayrollEntry> payroll(List<Employee> employees) {},规则如下:

  • 仅Worker和Manager类实例有bonus
  • Trainee类实例无bonus
  • 必须使用函数式编程技术实现
现有实现问题

当前代码会抛出ClassCastException,原因是直接将所有Employee实例强转为Worker,但Trainee不属于Worker的继承链:

public static List<PayrollEntry> payroll(List<Employee> employees) {
    return employees
            .stream()
            .map(employee -> new PayrollEntry(employee, employee.getSalary(), ((Worker) employee).getBonus()))
            .collect(Collectors.toList());
}
解决方案

直接在map操作中加入类型判断即可,Trainee的bonus传入BigDecimal.ZERO:

public static List<PayrollEntry> payroll(List<Employee> employees) {
    return employees.stream()
            .map(employee -> {
                BigDecimal bonus = employee instanceof Worker ? ((Worker) employee).getBonus() : BigDecimal.ZERO;
                return new PayrollEntry(employee, employee.getSalary(), bonus);
            })
            .collect(Collectors.toList());
}

如果使用Java 16及以上版本,可通过模式匹配简化类型转换代码:

public static List<PayrollEntry> payroll(List<Employee> employees) {
    return employees.stream()
            .map(employee -> new PayrollEntry(
                    employee,
                    employee.getSalary(),
                    employee instanceof Worker w ? w.getBonus() : BigDecimal.ZERO
            ))
            .collect(Collectors.toList());
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 23:45:01