I have a for
loop as below which is working fine.
try {
Accountant accountant = getAccountant(employees);
for (Employee person : employees) {
accountant.pay(person, this); // throws BudgetIsOverException
}
allSalariesPaid = true;
}
catch (BudgetIsOverException e){
allSalariesPaid = false;
}
But when I use a stream API instead, it asks me to handle the BudgetIsOverException
and shows an error at accountant.pay
even though it is properly caught after the try
statement. Below the code:
try {
Accountant accountant = getAccountant(employees);
employees.stream()
.forEach(e->accountant.pay(e,this)); // throws BudgetIsOverException
allSalariesPaid = true;
}
catch (BudgetIsOverException e) {
allSalariesPaid = false;
}
My question is why is stream API expecting an exception to be caught inside the foreach
block?
The foreach construct expects a consumer object
void forEach(Consumer<? super T> action);
The abstract method of consumer is
void accept(T t);
Note the above abstract method of consumer does not throw any checked exception so you need to handle it for each employee object unlike in above foreach loop. You could just handle and rethrow runtime exception.Its not a recommended way but the above code implies you are good to exit as soon as one of the employee's pay fail so we could go ahead with it.
private void method() {
try {
Accountant accountant = getAccountant(employees);
employees.stream()
.forEach(emp -> paySalary(accountant, emp, this));
allSalariesPaid = true;
}catch(RuntimeException e){
allSalariesPaid = false;
}
}
private void paySalary(Accountant accountant, Employee emp, CurrentClass currentClassRef) {
try {
accountant.pay(emp, currentClassRef);
} catch (BudgetIsOverException exception) {
throw new RuntimeException(exception);
}
}