It is difficult to make a program perfect, and there will inevitably be various abnormalities. For example, there is a bug in the program itself, such as the printer runs out of paper when the program prints, or there is insufficient memory. In order to solve these exceptions, we need to know why the exception occurred. For some common exceptions, we can also provide certain response plans. Exception handling in C language is simply implemented through function return values, but the meaning of the return value is often determined by convention. Programmers need to query a large amount of information before they can find a vague reason. Object-oriented languages, such as C++, Java, and Python, often have more complex exception handling mechanisms. The exception handling mechanism in Java is discussed here.
Java exception handling
Exception handling
A large part of Java's exception handling mechanism comes from C++. It allows programmers to skip problems that cannot be handled temporarily to continue subsequent development, or to allow the program to handle exceptions more intelligently.
Java uses some special objects to represent abnormal conditions, such objects are called exception objects. When an exception occurs, Java will throw an object representing the current situation based on preset settings. The so-called throwing is a special way of return. The thread will pause and exit method calls layer by layer until it encounters an exception handler. The exception handler can catch the exception object and decide the next action based on the object, such as:
Remind the user to handle exceptions and continue the program to exit the program
...
The exception handler looks like this, it consists of try, catch, finally and the following blocks. finally is not required.
try { ...;}catch() { ...;}catch() { ...;}finally { ...;}
This exception handler monitors the program block following try. The catch parentheses have a parameter that represents the type of exception to be caught. catch will capture the corresponding type and its derived classes. The program block after try contains the operations to be performed for the exception type. The program block monitored by try may throw more than one type of exception, so an exception handler can have multiple catch modules. The program block after finally is a program that must be executed regardless of whether an exception occurs.
We put programs that may go wrong and need to be monitored in try, and design solutions to deal with exceptions in catch.
The following is a partial Java program that uses exception handling. The try part of the program reads lines of text from a file. During the process of reading the file, an IOException may occur:
BufferedReader br = new BufferedReader(new FileReader("file.txt"));try { StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line) ; sb.append("/n"); line = br.readLine(); } String everything = sb.toString();} catch(IOException e) { e.printStackTrace(); System.out.println("IO problem");}finally { br.close();}
If we catch the IOException class object e, we can operate on the object. For example, call the object's printStackTrace() to print the current stack status. In addition, we also printed the prompt "IO problem" to the midrange.
Regardless of whether there is an exception or not, the program will eventually enter the finally block. We close the file in the finally block and clear the resources occupied by the file descriptor.
exception type
Exception classes in Java all inherit from the Trowable class. An object of the Throwable class can be thrown (throw).
Orange: unchecked; blue: checked
Throwable objects can be divided into two groups. One group is unchecked exceptions. Exception handling mechanisms are often not used for this group of exceptions, including:
1. The Error class usually refers to Java's internal errors and errors such as resource exhaustion. When an Error (and its derivatives) occurs, we cannot solve the Error at the programming level, so we should exit the program directly.
2. The Exception class has a special derived class RuntimeException. RuntimeException (and its derivatives) are caused by the Java program itself, that is, due to the programmer making mistakes while programming. RuntimeException can be completely avoided by modifying the Java program. For example, converting an object of one type into another type without inheritance relationship is a ClassCastException. Such anomalies should and can be avoided.
The rest are checked exceptions. These classes are caused by programming interactions with the environment that cause errors in the program at runtime. For example, when reading a file, an IOException occurs due to an error in the file itself. Another example is that the network server temporarily changes the URL pointing, causing MalformedURLException. The file system and network server are outside the Java environment and are not within the control of the programmer. If programmers can anticipate exceptions, they can use the exception handling mechanism to develop response plans. For example, when there is a problem with a file, the system administrator is alerted. Another example is when there is a problem with the network server, the user is reminded and waits for the network server to recover. The exception handling mechanism is mainly used to handle such exceptions.
throw an exception
In the above program, the exception comes from our call to the Java IO API. We can also throw exceptions in our own programs, such as the following battery class, which has charging and usage methods:
public class Test{ public static void main(String[] args) { Battery aBattery = new Battery(); aBattery.chargeBattery(0.5); aBattery.useBattery(-0.5); }}class Battery { /** * increase battery * / public void chargeBattery(double p) { // power <= 1 if (this.power + p < 1.) { this.power = this.power + p; } else { this.power = 1.; } } /** * consume battery */ public boolean useBattery(double p) { try { test(p); } catch(Exception e) { System. out.println("catch Exception"); System.out.println(e.getMessage()); p = 0.0; } if (this.power >= p) { this.power = this.power - p; return true; } else { this.power = 0.0; return false; } } /** * test usage */ private void test(double p) throws Exception // I just throw, don't handle { if ( p < 0) { Exception e = new Exception("p must be positive"); throw e; } } private double power = 0.0; // percentage of battery}
useBattery() indicates using battery operation. There is a parameter in the useBattery() method, indicating the amount of electricity used. We use the test() method to test this parameter. If this parameter is negative, then we think there is an exception and throw it.
In test, when an exception occurs (p < 0), we create an Exception object e and use a string as a parameter. The string contains exception-related information and this parameter is not required. Use throw to throw the Exception object.
We have exception handler in useBattery(). Since the test() method does not directly handle the exception it generates, but throws the exception to the upper useBattery(), we need to explain throws Exception in the definition of test().
(Assuming that the exception handler is not located in useBattery(), but in the higher-level main() method, we also need to add throws Exception to the definition of useBattery().)
In catch, we use the getMessage() method to extract the information contained in its exception. The results of running the above program are as follows:
catch Exceptionp must be positive
In the exception handler, we will catch any exception of the Exception class or its derivatives. This often does not help us identify problems, especially when a program may throw multiple exceptions. We can provide a more specific class to capture.
Custom exception
We can create new exception classes through inheritance. When inheriting, we often need to override the constructor. Exceptions have two constructors, one with no parameters and one with a String parameter. for example:
class BatteryUsageException extends Exception{ public BatteryUsageException() {} public BatteryUsageException(String msg) { super(msg); }}
We can provide more exception-related methods and information in derived classes.
When customizing exceptions, be careful about which base class you inherit from. A more specific class should contain more exception information, such as IOException versus Exception.
Summarize
Exception handling is solving problems, but it is also creating problems. In large projects, excessive and detailed exception handling often causes the program to become a mess. Exception handling is not simple by design and needs to be used with caution.