Use exceptions only for exceptional situations
What’s wrong with the code above?
– Trying to terminate an infinite loop by throwing an exception and ignoring it; Intended to avoid out-of-bounds checks for the for loop; – However: 1. The exception mechanism is designed for abnormal situations, so few JVMS optimize it; 2. Putting code in a try-cache prevents modern JVMS from implementing specific optimizations that might otherwise be performed; 3. For traversal does not cause redundant checks, and some modern JVMS optimize them out; The code – the code above fuzzy intentions, reduces the performance, also can’t guarantee the normal work, for example in the loop body calculation procedure calls a method, this method performs on a don’t want to close the array of cross-border access, abnormal, and the try block will ignore this bug, increased the complexity of the debugging process.
Lessons for API design: A well-designed API should not force its clients to use exceptions for normal control flow; For example, Iterator has a hasNext method to determine whether to terminate the loop. If it is not provided, the user might be forced to use the code above.
In short, exceptions are designed to be used in exceptional situations, not in normal control flow, and don’t write aN API that forces others to do so;
Use checked exceptions for recoverable cases and run time exceptions for programming errors
Three types of Throwable structures in Java: – Checked exception – run-time exception – Error
If the caller is expected to recover properly, force the caller to handle the modified exception in a catch clause or propagate it by throwing a checked exception.
The API designer forces the API user to respond to the exception condition by exposing the user to it. Users can ignore such mandates by simply capturing and ignoring them, but this is often not a good idea; If the File, IO flow operation is a common IOException, FileNotFoundException;
The other two are not needed and should not be captured;
Use runtime exceptions to indicate programming errors; Most represent precondition violation; Premise violation is refers to the API user not comply with the provisions of the API specification to build, such as ArrayIndexOutOfBoundsException NullPointerException.
Errors are reserved by the JVM to indicate insufficient resources, constraint failure, or other conditions that prevent the program from continuing; So it’s best not to implement any new Error subclasses;
API designers tend to forget that the anomaly is a completely sense objects, you can define any methods on it, these methods mainly used for code to catch exceptions to provide additional information, a. abnormalities tend to indicate the terms of recoverable, so for such an exception, with some auxiliary methods is particularly important, Can help the caller get some information to help recover;
Avoid unnecessary use of checked exceptions
Checked exceptions force programmers to deal with, greatly enhancing the reliability; Excessive use of checked exceptions can make the API very inconvenient to use (try-catch or throw);
So be careful with checked exceptions when designing your API. If the programmer using the API can’t do better than the following, then using unchecked exceptions is more appropriate;
In fact, if you think back to writing code like this, you should ask yourself if there is another way to avoid checking exceptions;
One solution is to split the method that throws an exception into two methods, one of which returns Boolean, which uses an if judgment to handle both cases of whether or not to throw an exception. As mentioned earlier, Iterator has a hasNext method;
(However, you may lose the constraint that API users do not necessarily call methods such as iterator.hasnext (), which requires proper API documentation to regulate user calls.)
Standard exceptions are preferred
One key difference between the expert and the novice: a high degree of code reuse. This is a general rule, and exceptions are no exception. This article discusses common reusable exceptions (unchecked);
Benefits of reusing existing exceptions: 1. Make the API easier to learn and use (generic, idiomatic);
2. Better readability (fewer unfamiliar exceptions) for programs using these apis; 3. The fewer the exception classes, the smaller the memory footprint and the less time it takes to load these classes;
If you want to add more fail-catch information, you can subclass existing exceptions.
Common exceptions:
– IllegalArgumentException: illegal parameters (the caller and inappropriate);
– IllegalStateException: Indicates an illegal state (the state of an object in the called program does not meet the program running requirements).
– NullPointerException: NullPointerException: NullPointerException: NullPointerException: NullPointerException: NullPointerException: NullPointerException
– IndexOutOfBoundsException: this also is very familiar with, array operation often meet his subclass.
– ConcurrentModificationException: if an object is designed to be dedicated to a single thread or used together with external synchronization mechanism, once found that it is or has been concurrent modifications, you should throw the exception;
– UnsupportedOperationException: object does not support the user request method;
Throws an exception corresponding to the abstraction
If a method throws an exception that has no obvious connection to the task it is performing, it can be overwhelming; This tends to happen when passing exceptions thrown by low-level abstractions, which also contaminate the higher-level API with implementation details;
Exception translation: Higher-level implementations should catch low-level exceptions and throw exceptions that can be interpreted in terms of higher-level abstractions;
Exception chain: If the low-level exception is useful for debugging the problem that caused the high-level exception, you can pass the low-level exception to the high-level exception, which provides access (throwable.getCause ()) to get the low-level exception:
The best way to handle exceptions from low-level methods is to ensure that they will execute successfully before calling them to avoid them throwing exceptions, such as checking the validity of arguments;
If this is unavoidable, the second option is to have higher-level methods quietly bypass these exceptions, thereby isolating the callers of higher-level methods from low-level problems by using appropriate logging mechanisms to log exceptions and help administrators investigate the problem.
Every exception thrown by a method should be documented
Always declare checked exceptions separately and record exactly the conditions under which each exception is thrown using javadoc’s @throws tag.
When a method needs to throw multiple Exception classes, do not use superclasses of those exceptions or exceptions,Throwable, instead of providing guidance on what exceptions the method can throw. And it greatly hampers its use, because it actually masks any other exceptions that the method might throw in the same execution environment;
It is best to record unchecked exceptions using the @throws tag of Javadoc as well, but do not use the throws keyword to include unchecked exceptions in method declarations.
If many methods in a class throw the same exception for the same reason, it is ok to document the exception in the class’s documentation comments. All methods in this class throw a NullPointerException if a null object reference is passed in any parameter;
Include information to catch failures in the detail message
To catch failures, the exception details should contain all parameters and field values that “contributed to the exception”; When the program fails due to an uncaught exception, the system automatically prints the stack trace of the exception, which contains the string representation of the exception, that is, the result of calling the toString method.
Because exceptions can be difficult to reproduce, the toString (details) should return as much information as possible about the cause of the failure; (and fail to capture, abnormal information should contain all the details of the “contribute to the abnormal values of the parameters and the domain), the use of the stack trace is combined with the source file is analyzed, it usually contains throws the exception of the exact file and line number, and all the other method call stack in the file and line number)
Exception details should not be confused with “user-level error messages,” which must be understandable to the end user. The former allows the programmer to analyze the cause of the failure. The content of the message is more important than understandability. To ensure sufficient information, one approach is to introduce this information into the exception constructor as follows:
Try to keep failure atomic
Definition: Failed method calls should leave the object in the same state as before they were called. Methods with this property are said to have failed atomicity.
The simplest way is to design an immutable object;
A common approach to mutable objects:
1. Check the validity of the parameters, before performing actions that can be made before the state of an object is modified, an appropriate exception first, as I speak before stack ArrayStack pop method in the article, if the cancellation of the size of the initial inspection, when this method attempts to pop up from an empty stack elements, it will still be an exception is thrown, and, This will cause any future method calls to the object to fail;
2. Adjust the sequence of the calculation process so that any possible calculation failures occur before the object state is modified; For example, to add an element to TreeMap’s PUT method, the element must be of a type that can be compared with other elements using TreeMap’s sorting rules. Attempting to add an element of the wrong type will naturally result in a ClassCastException before the tree is modified in any way.
3. Write recovery code that intercepts failures during operations and rolls objects back to the state before operations began, mainly for persistent (disk-based) data structures; 4. Perform an operation on a temporary copy of an object. After the operation is complete, replace the contents of the object with the result of the temporary copy.
Don’t ignore exceptions
When API designers say that a method will throw an exception, they are trying to say something, so don’t ignore it;
It is easy to ignore an exception as follows:
At a minimum, the catch block should also contain a statement explaining why the exception can be ignored;
Ignoring it with an empty catch block will cause the program to silently execute in the event of an error, and then at some point in the future, when the program can no longer tolerate problems that are clearly related to the source of the error, it will fail;
As long as the exception is propagated to the outside world, the program can at least fail quickly, thus preserving information that helps debug the failure condition.
I am Jinyang, if you want to advance and learn more dry goods, welcome to pay attention to the public number “jinyang said,” receive my latest article