The time for argument has passed.
- the beginning of the chapter “Use unchecked exceptions” of the book “Clean Code” by Robert Martin.
No matter how much Mike Fiesers (the author of the epigraph quotation) would like to put an end to the dispute "checked vs unchecked exceptions", today, more than five years later, we have to admit that this topic still remains "holivar." The community of programmers is divided into two camps. Both sides are compelling arguments. Among those and others there are top-class developers: Bruce Eckel
criticizes the concept of checked exceptions , James Gosling
protects . It seems that this question will never be completely closed.
Five years ago, the advice to abandon the checked exceptions caused me to be perplexed and outraged. The Java textbooks explained when to use them, but here it is ... I had no Java development experience at all, so I could only take one of the two on trust, and I rejected the advice from Clean Code.
I have never been wrong in my life.')
But this article will discuss serious reasons for believing that the convenience of checked exceptions is a myth. Many articles are devoted to this issue, but I will try to look at the problem from a slightly different side, to give my arguments and examples. Close the topic early.
In general,
this is my first post, do not judge strictly welcome under cat.
As intended
The only reason for the existence of different types of exceptions is the different ways to handle them:
- Established errors, the processing of which is part of the business logic. Example: a user entered an incorrect password - display the corresponding message and ask to enter again. For such situations, according to Java authors, you need to use checked exceptions.
- Unexpected errors, in the case of which we say to the user “something has broken here,” log the stack trace and open the ticket in the bugtracker. In this case, we are talking about unchecked exceptions.
Since regular situations must necessarily be processed, Gosling and the company decided to put control on the compiler: they say, they forgot to process it - an error, it is impossible to start it. How it works, we know: either we catch an exception, or we specify it in the list of throws.
But what happens when the checked exception is processed many levels higher? It should be added to signatures of many methods. And the more they appear, the "more fun". Not so convenient, but maybe this is a necessary evil?
Why are we being offered to endure these obsessive “throws”, inconveniences with lambdas in Java 8, etc.? Consider the arguments for checked exceptions:
- “The mechanism of checked exceptions ensures that all regular situations will be handled. This allows you to create more reliable software. "
- “In languages without checked exceptions, developers may not specify possible exceptions in the method signature, as a result it is not always clear what kind of pitfalls to expect from it. In Java, the compiler will not allow this. ”
Now the objections.
To check or not to check?
Consider the signature of the FileInputStream constructor:
public FileInputStream(File file) throws FileNotFoundException
, — , FileNotFoundException, .
, . , - , , . FileNotFoundException , - NPE, , - :
catch(Exception e){
LOGGER.error("Fatal error", e);
return new Response(500, "Oops, unexpected error on server");
}
, , . «»?
— , !
— RuntimeException ?
— 500!
— FileNotFoundException , , throws.
- , , , , , . , ,
, .
?
, : ValidationException — 400 , AccessDeniedException — 403, ResourceNotFoundException — 404 ..
unchecked, :
catch(ValidationException e){
return new Response(400, e.getMessage());
}
catch(AccessDeniedException e){
return new Response(403, e.getMessage());
}
catch(ResourceNotFoundException e){
return new Response(404, e.getMessage());
}
.
: , throws . , , : — ApplicationNameException. (checked !):
catch(ValidationException e){
return new Response(400, e.getMessage());
}
catch(AccessDeniedException e){
return new Response(403, e.getMessage());
}
catch(ResourceNotFoundException e){
return new Response(404, e.getMessage());
}
catch(ApplicationNameException e){
// todo
}
catch? , , ApplicationNameException , Exception: «- ». :
catch(ValidationException e){
return new Response(400, e.getMessage());
}
catch(AccessDeniedException e){
return new Response(403, e.getMessage());
}
catch(ResourceNotFoundException e){
return new Response(404, e.getMessage());
}
catch(ApplicationNameException e){
LOGGER.error("Unknown error", e.getMessage());
return new Response(500, "Oops");
}
: , , catch. , NPE. «!» — checked exceptions. , : ApplicationNameException , .
: throws, . ?
, ( , ).
throws Exception
throws? Exception! :
public void doSome() throws Exception{
// do some
}
«throws Exception»? - . RuntimeException?
—
try{
// some code
} catch(IOException e){
}
stack traces
try{
// some code
} catch(IOException e){
throw new MyAppException("Error");
}
, ? «throws Exception» — .
, ?
, . , ,
?
, .
, . , , , .
- ,
. ?
, checked exceptions — , .
, . . unchecked exceptions, .
, , . , — Java. , . , , . .
Java , :
String s = "hello";
if(s != null){
System.out.println(s.length());
}
.