Проблема с созданием исключений
Код - простецкий симулятор банкомата. Задание - тренировка во встраивании обработки исключений в код.
Atm.java
package ex2.atm;
import java.math.BigDecimal;
public class Atm {
Atm() {
}
boolean isCardInserted(Card card) {
if (card != null) {
System.out.println("card inside");
return true;
} else
System.out.println("card already inside");
return false;
}
String showBalance(Card card) {
if (isCardInserted(card)) {
System.out.println(card.getBalance());
return null;
} else {
System.out.println("Вставьте карту");
return null;
}
}
public void withdraw(Card card, BigDecimal request) {
BigDecimal zero = new BigDecimal(0);
if (((card.getBalance().subtract(request)).compareTo(zero)) < 0) {
if (card.isCredit()) {
card.creditIncreased(request);
System.out.println("Вы должны банку: " + card.getDebt().multiply(BigDecimal.valueOf(-1)));
} else System.out.println("Ваша карта не является кредитной");
} else {
card.setBalance(card.getBalance().subtract(request));
}
}
}
Card.java
package ex2.atm;
import java.math.BigDecimal;
abstract class Card {
private long serialNumber;
private BigDecimal balance;
private boolean credit;
private BigDecimal debt;
protected Card() {
}
public Card(long serialNumber, BigDecimal balance, boolean credit, BigDecimal debt) {
this.serialNumber = serialNumber;
this.balance = balance;
this.credit = credit;
this.debt = debt;
}
void creditIncreased(BigDecimal request) {
this.balance = (BigDecimal.valueOf(0));
BigDecimal tempBal = bigDecSub(this.balance, request);
BigDecimal anotherTempBal = bigDecAdd(this.debt, tempBal);
this.debt = (anotherTempBal);
}
BigDecimal bigDecSub(BigDecimal plus, BigDecimal minus) {
return plus.subtract(minus);
}
BigDecimal bigDecAdd(BigDecimal plus, BigDecimal minus) {
return plus.add(minus);
}
BigDecimal getBalance() {
return balance;
}
public void setBalance(BigDecimal balance) {
this.balance = balance;
}
public boolean isCredit() {
return credit;
}
public BigDecimal getDebt() {
return debt;
}
@Override
public String toString() {
return "Card{" +
"serialNumber=" + serialNumber +
", balance=" + balance +
", credit=" + credit +
", debt=" + debt +
'}';
}
}
Main.java
package ex2.atm;
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
Visa visa = new Visa(1921682550, BigDecimal.valueOf(5000), false, BigDecimal.valueOf(0));
Atm teller = new Atm();
System.out.println(teller.showBalance(visa));
teller.withdraw(visa, BigDecimal.valueOf(700));
}
}
Visa.java
package ex2.atm;
import java.math.BigDecimal;
public class Visa extends Card {
public Visa(long serialNumber, BigDecimal balance, boolean credit, BigDecimal debt) {
super(serialNumber, balance, credit, debt);
}
}
Вопрос: Подскажите, а есть ли здесь вообще места, где можно хоть какие-то исключения обработать. Если есть - не пишите готовый код. Лучше скажите что-то типа:
"в методе isCardInserted/Atm используй tryWithResourses для sout с исключением IOException".
Или может что-то добавить можно/нужно, чтобы создать "исключительные" ситуации. Просто сколько читал всякие обучалки, там везде обработка исключений строится на BufferedReader, а у меня всяких потоков нет.
Ответы (2 шт):
Не вижу какие системные ошибки можно обрабатывать в Вашем примере. Вы действительно не обращаетесь ни к каким внешним ресурсам, которые могут выбрасывать ошибки, не зависящие от Вас (потоки, файлы, базы данных, и т.п.).
Но исключения используются не только для работы с внешними ресурсами, но и для внутренней логики приложения, т.ч. можно попробовать выбрасывать исключения самому и затем их обрабатывать.
Например, в методе Atm.withdraw Вы проверяете условие, что с некредитной карты нельзя снять сумму больше баланса. В этом случае Вы напрямую выводите сообщение пользователю.
else System.out.println("Ваша карта не является кредитной");
Вместо этого можно выбрасывать в этом случае исключение, и обрабатывать его в try-catch.
Это будет выглядит логичнее если withdraw будет методом класса Card. Так в классе Card будет проверка условий и выбрасывание исключений, а в классе Atm вызов методов, обработка исключений и вывод сообщений для пользователя.
Вообще, если все методы, изменяющие баланс будут в Card, то можно будет добиться того, что карточка никогда не окажется в неправильном состоянии. Сейчас класс Atm может сделать так для любой карты:
card.setBalance(BigDecimal.valueOf(-1000));
Если метода setBalance не будет, или же он будет private, то так уже не получится.
Преимуществом использования исключений в том что они прерывают работу любого метода в котором они не обрабатываются, что позволяет выполнять сложные операции и обрабатывать исключения централизованно:
try {
card.withdraw(BigDecimal.valueOf(400));
...
card.withdraw(BigDecimal.valueOf(1000));
card.transfer(BigDecimal.valueOf(100));
} catch(Exception e) {
//выполняются разные методы, но ошибки можно обработать в одном месте
}
Исходя из логики приложения (симулятор банкомата), я бы предположил, что исключение надо выбрасывать в случае каких-то ошибок карты (например не читается карта) - в общем случае обычно это проверяется вызовом проверки готовности устройства перед началом работы:
public boolean isCardReady(Card card) throws HardwareException {
if(card == null)
return false;
return true; //на симуляторе всегда true
}
public boolean isAtmReady(Atm atm) throws HardwareException {
if (atm == null)
return false;
return true;
}