同步 · dev.to / @markyu
A practical Java exception handling guide explaining throw, throws, checked exceptions, runtime exceptions, and API boundary decisions.
- 发布日期
- May 22 '24
- 阅读时长
- 2 min read
- 点赞
- 5
javabackendprogrammingbeginners
throw and throws are easy to memorize and still easy to misuse.
The real difference is not grammar.
throw is the moment you raise an exception. throws is the method contract that warns callers an exception may escape.
The Short Version
| Keyword | Where it appears | What it means |
|---|---|---|
throw | inside method body | raise this exception now |
throws | method signature | this method may pass this exception upward |
throw: Fail Here
public User findUser(String id) {
if (id == null || id.isBlank()) {
throw new IllegalArgumentException("User id is required");
}
return repository.findById(id);
}This is a direct failure.
I like this for invalid programmer input or impossible states. Do not let bad data travel deeper into the system.
throws: Caller Must Deal With It
public String readConfig(String path) throws IOException {
return Files.readString(Path.of(path));
}The method is saying:
I might fail with
IOException, and I am not handling it here.
Caller:
try {
String config = readConfig("app.yml");
} catch (IOException e) {
log.error("Failed to read config", e);
}Checked vs Runtime Exceptions
Checked exceptions must be handled or declared:
public void load() throws IOException {
Files.readString(Path.of("app.yml"));
}Runtime exceptions do not need throws:
throw new IllegalArgumentException("Bad request");My rough rule:
- Use checked exceptions when the caller can reasonably recover.
- Use runtime exceptions for programming mistakes or invalid state.
Do Not Swallow Exceptions
This is the code smell:
try {
sendEmail();
} catch (Exception e) {
// ignore
}If the email matters, ignoring the exception lies to the system.
At least log it or return a failure result:
try {
sendEmail();
} catch (MailException e) {
log.warn("Email send failed for user {}", userId, e);
}API Boundary Example
Inside infrastructure code:
public User loadUser(String id) throws SQLException {
// database call
}At the service boundary, I usually translate it:
public User getUser(String id) {
try {
return userDao.loadUser(id);
} catch (SQLException e) {
throw new UserLookupException("Failed to load user " + id, e);
}
}This keeps SQL details from leaking everywhere.
Final Thought
throw is an action. throws is a warning label.
Good exception design is mostly about choosing where a failure should be handled and where it should be translated.
Do you prefer checked exceptions or runtime exceptions in Java service code?
相关阅读
Java final, finally, finalize: Three Bugs They Prevent
A practical Java explanation of final, finally, and finalize using real failure modes instead of memorized definitions.
java
Java BeanUtils Copying: Convenient, but Not Free
A practical Java guide to BeanUtils, shallow copy pitfalls, reflection overhead, and when MapStruct or manual mapping is a better choice.
java
Frontend Linear Data Structures Deep Dive: Arrays, Stacks, Queues, and Linked Lists
The Big Picture Before diving into stacks, queues, and linked lists, it helps to know...
computerscience
原文发布
本文首发于 dev.to,评论与点赞保留在原站。
在 dev.to 继续阅读