程序需先用hasnextint()预检再读取,失败时调用next()消费非法token;金额用int存“分”避免浮点误差;余额校验与扣减须原子化;异常要转为用户提示并continue重试,不可throws中断流程。

输入非数字时程序直接崩溃?用 Scanner.hasNextInt() 预检再读
用户输个 "abc" 或直接回车,nextInt() 就抛 InputMismatchException,整个流程中断。这不是“异常没捕获”,而是根本没给它读的机会——得先问“你接下来是不是整数?”
- 永远别在
try里硬调nextInt(),先用scanner.hasNextInt()判断 - 判断为
false后必须调scanner.next()消费掉非法 token,否则下次判断还是false(卡死) - 如果要支持小数金额,改用
hasNextDouble()+nextDouble(),但注意浮点精度问题,业务上建议统一用int表示分
余额不足却扣款成功?取款逻辑必须原子化校验+更新
先判断余额够不够,再执行减法——这中间如果有并发或手动调试干扰,就可能绕过检查。控制台虽无并发,但逻辑漏洞会惯性带到后续真实场景。
- 把“检查”和“扣减”写进同一个
if分支,不拆成两步 - 扣款后立刻打印当前余额,而不是只打印“取款成功”,避免掩盖实际未扣款的假象
- 金额参数用
int而非double,比如存 10000 表示 100.00 元,彻底避开0.1 + 0.2 != 0.3这类问题
异常被捕获但用户没感知?别只写 e.printStackTrace()
控制台程序里堆栈跟踪对用户毫无意义,反而暴露实现细节。真正该告诉用户的只有三件事:哪里错了、为什么错、现在能做什么。
- 捕获
InputMismatchException时,输出 “请输入有效的数字” - 捕获自定义的
InsufficientBalanceException(推荐显式抛出),输出 “余额不足,请重新输入” - 所有
catch块末尾加continue(放在循环内),让用户能立刻重试,而不是退出程序
为什么不用 throws 往上扔异常?控制台交互必须当场闭环
main 方法声明 throws Exception 看似省事,但会导致任何异常都终止程序并打印堆栈——用户输错一次就得重启,体验断裂。
立即学习“Java免费学习笔记(深入)”;
- 控制台交互是线性流程,每一步失败都应原地恢复,不是让 JVM 接管
- 哪怕只是
NumberFormatException,也要在本层消化,转成用户可理解的提示 - 唯一适合往上抛的,是打开配置文件失败这类初始化错误,但取款逻辑本身必须自包含容错
最易被忽略的是:每次异常后,Scanner 的缓冲区状态可能残留换行符,导致下一轮 nextLine() 读到空字符串。遇到这种现象,别急着改逻辑,先在 catch 里补一句 scanner.nextLine() 清一下。










