Analyzing the Java exception mechanism: catching errors in programming to ensure code stability

At work, the situation encountered by the program cannot be perfect. For example: the program wants to open a certain file, the file may not exist or the file format is wrong; the program is running, but the memory or hard disk may be full, etc.

During the running of a software program, it is very likely to encounter the problems just mentioned. We call them exceptions. English is: Exception, which means exceptions. When encountering these exceptions, or called exceptions, how can we make the written program handle it reasonably and exit safely without the program crashing? Let me introduce:

⭐ Exception mechanism

If we want to copy a file, in the absence of an exception mechanism, we need to consider various exceptions, the pseudo
code is as follows:

[Example] Pseudocode: There are two disadvantages of using if to handle various situations that may occur in the program :
insert image description here

  1. Put logic code and error handling code together!

  2. The exceptions that programmers themselves need to consider are more complicated, and the requirements for programmers themselves are higher!
    For the above situation, if it is handled by Java exception mechanism, the comparison is as follows:
    insert image description here

     异常机制本质
     当程序出现异常,程序安全的退出、处理完后继续执行的机制
    

⭐ The concept of Exception

Abnormalities refer to abnormal phenomena that occur during the running of the program, such as the divisor is zero, the file to be processed does not exist, and the array subscript is out of bounds.

In Java's exception handling mechanism, many classes used to describe and handle exceptions are introduced, called exception classes. The exception class definition contains the information of this type of exception and the method of handling the exception.

Let's start by looking at our first exception object and analyze how the exception mechanism works.

[Example] Abnormal Analysis

public class Test {
    
    
 public static void main(String[] args) {
    
    
 System.out.println("111");
 int a = 1/0;
 System.out.println("222");
 }
}

The execution result is as follows:
insert image description here

According to the result, we can see that an exception occurred when executing "1/0", the program terminated, and the subsequent action of printing "222" was not executed.

If we use try-catch to handle it, the program can handle it normally when it encounters an exception. After the processing is completed, the program continues to execute:

public class Test {
    
    
 public static void main(String[] args) {
    
    
 System.out.println("111");
 try {
    
    
 int a = 1/0;
 } catch (Exception e) {
    
    
 e.printStackTrace();
 }
 System.out.println("222");
 }
}

The execution results are as follows:
insert image description here

The program still encounters an exception during the execution of "1/0", and then try-catch processing. After the processing is completed, the program continues to execute, and the content of "222" is printed.

Java handles exceptions in an object-oriented way. Process:

⭐	抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给 JRE。
⭐	捕获异常:JRE 得到该异常后,寻找相应的代码来处理该异常。JRE 在方法的调用栈中查找,从生成异常的方法开始回溯,直到找到相应的异常处理代码为止。

⭐ Exception Classification

Many exception classes are defined in Java, which correspond to various possible exception events, and all exception objects are derived from an instance of the Throwable class. If the built-in exception class cannot meet your needs, you can also create your own exception class.

Java classifies exceptions. Different types of exceptions are represented by different Java classes. The root class of all exceptions is java.lang.Throwable, and two subclasses are derived from Throwable: Error and Exception. The hierarchy of Java exception classes is shown in the figure:
insert image description here

Error

Error is an error that the program cannot handle, indicating a serious problem in running the application. Most errors are not related to actions performed by the code writer, but represent problems with the JVM (Java Virtual Machine) when the code is running. For example, Java virtual machine operation error (Virtual MachineError), when the JVM no longer has the memory resources needed to continue the operation, OutOfMemoryError will appear. When these exceptions occur, the Java Virtual Machine (JVM) generally chooses the thread to terminate.

Error indicates that the system JVM has been in an unrecoverable crash state.
insert image description here

Error 与 Exception 的区别
⭐	我开着车走在路上,一头猪冲在路中间,我刹车。这叫一个异常。
⭐	我开着车在路上,发动机坏了,我停车,这叫错误。系统处于不可恢复的崩溃状态。发动机什么时候坏?我们普通司机能管吗?不能。发动机什么时候坏是汽车厂发动机制造商的事。

Exception

Exception is an exception that the program itself can handle.

The Exception class is the parent class of all exception classes, and its subclasses correspond to various possible exception events. Generally, Java exceptions can be divided into:

⭐	RuntimeException 运行时异常
⭐	CheckedException 已检查异常

RuntimeException runtime exception

Exceptions derived from RuntimeException, such as division by 0, array subscript out of bounds, null pointer, etc., are frequently generated and troublesome to handle. If they are explicitly declared or captured, they will have a great impact on program readability and operating efficiency. They are therefore automatically detected by the system and handed over to the default exception handler.

The compiler does not handle RuntimeException, programmers need to add "logic processing to avoid these exceptions".

[Example] ArithmeticException: Attempt to divide by 0

public class Test3 {
    
    
	public static void main(String[ ] args) {
    
    
	int b=0;
	System.out.println(1/b);
	}
}

The execution result is as follows:
insert image description here

To solve the above exception, you need to modify the code:

public class Test3 {
    
    
	public static void main(String[ ] args) {
    
    
		int b=0;
		if(b!=0){
    
    
		System.out.println(1/b);
		}
	}
}

[Example] NullPointerException exception

public class Test4 {
    
    
	public static void main(String[ ] args) {
    
    
		String str=null;
		System.out.println(str.charAt(0));
	}
}

The execution result is as follows:
insert image description here

To solve the null pointer exception, it is usually to increase the non-null judgment:

public class Test4 {
    
    
	public static void main(String[ ] args) {
    
    
		String str=null;
		if(str!=null){
    
    
		System.out.println(str.charAt(0));
		}
	}
}

[Example] ClassCastException exception

class Animal{
    
    
}
class Dog extends Animal{
    
    
}
class Cat extends Animal{
    
    
}
public class Test5 {
    
    
	public static void main(String[ ] args) {
    
    
		Animal a=new Dog();
		Cat c=(Cat)a;
	}
}

The execution result is as follows:
insert image description here

Typical way to resolve ClassCastException:

public class Test5 {
    
    
	public static void main(String[ ] args) {
    
    
		Animal a = new Dog();
		if (a instanceof Cat) {
    
    
		Cat c = (Cat) a;
		}
	}
}

[Example] ArrayIndexOutOfBoundsException exception

public class Test6 {
    
    
	public static void main(String[ ] args) {
    
    
		int[ ] arr = new int[5];
		System.out.println(arr[5]);
	}
}

The execution result is as follows:
insert image description here

The way to solve the array index out-of-bounds exception is to increase the judgment about the boundary:

	public class Test6 {
    
    
		public static void main(String[ ] args) {
    
    
			int[ ] arr = new int[5];
			int a = 5;
			if (a < arr.length) {
    
    
			System.out.println(arr[a]);
		}
	}
}

[Example] NumberFormatException exception

	public class Test7 {
    
    
		public static void main(String[ ] args) {
    
    
		String str = "1234abcf";
		System.out.println(Integer.parseInt(str));
	}
}

The execution result is as follows:
insert image description here

To solve the abnormal number formatting, you can introduce regular expressions to judge whether it is a number:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
	public class Test7 {
    
    
		public static void main(String[ ] args) {
    
    
			String str = "1234abcf";
			Pattern p = Pattern.compile("^\\d+$");
			Matcher m = p.matcher(str);
			if (m.matches()) {
    
     // 如果 str 匹配代表数字的正则表达式,才会转换
			System.out.println(Integer.parseInt(str));
		}
	}
}

⭐ CheckedException checked exception

insert image description here

CheckedException must be handled at compile time, otherwise it will fail to compile. as the picture shows.
insert image description here

There are two ways to handle CheckedException exceptions:

⭐	使用“try/catch”捕获异常
⭐	使用“throws”声明异常。

⭐ One of the exception handling methods: catch exception

insert image description here

try:

The try statement specifies a piece of code that is the scope of exception capture and processing. During execution, when any statement generates an exception, the following code in the statement will be skipped. One or several types of exception objects may be generated and thrown in the code, and the catch statement behind it should handle these exceptions accordingly.

A try statement must be accompanied by at least one catch statement block or one finally statement block.

注意事项
⭐	当异常处理的代码执行结束以后,不会回到 try 语句去执行尚未执行的代码。

catch:

⭐	每个 try 语句块可以伴随一个或多个 catch 语句,用于处理可能产生的不同类型的异常对象。
⭐	catch 捕获异常时的捕获顺序:
⭐	如果异常类之间有继承关系,先捕获子类异常再捕获父类异常。

finally:

⭐	不管是否发生了异常,都必须要执行。
⭐	通常在 finally 中关闭已打开的资源,比如:关闭文件流、释放数据库连接等。

Detailed analysis of the execution process of the try-catch-finally statement block:

The program first executes a block of try statements where an exception may occur. If there is no exception in the try statement, it will jump to the finally statement block after execution; if there is an exception in the try statement, it will interrupt the execution and jump to the corresponding catch statement block for processing according to the type of exception that occurs. There can be multiple catch statement blocks, each of which catches different types of exceptions. After the catch statement block is executed, the program will continue to execute the finally statement block. The finally statement is optional. If present, the finally statement will be executed regardless of whether an exception occurs.

[Example] Typical code for exception handling (catch exception)

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Test8 {
    
    
	public static void main(String[ ] args) {
    
    
		FileReader reader = null;
		try {
    
    
		reader = new FileReader("d:/a.txt");
		char c = (char) reader.read();
		char c2 = (char) reader.read();
	System.out.println("" + c + c2);
		} catch (FileNotFoundException e) {
    
    
		e.printStackTrace();
		} catch (IOException e) {
    
    
		e.printStackTrace();
		} finally {
    
    
		try {
    
    
		if (reader != null) {
    
    
		reader.close();
			}
		} catch (Exception e) {
    
    
		e.printStackTrace();
			}
		}
	}
}

In common development environments, shortcut keys for try-catch code blocks are automatically added:

⭐	将需要处理异常的代码选中。
⭐	IDEA 中,使用:ctrl+alt+t
⭐	eclipse 中,使用:ctrl+shift+z

⭐ The second way of handling exceptions: declaring exceptions (throws clause)

insert image description here

⭐	CheckedException 产生时,不一定立刻处理它,可以把异常 throws,由调用者处理。
⭐	一个方法抛出多个已检查异常,就必须在方法的首部列出所有的异常。

[Example] Typical code for exception handling (declare exception throws throws)

package oldwang;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Test9 {
    
    
 public static void main(String[ ] args) {
    
    
 try {
    
    
 readFile("joke.txt");
 } catch (FileNotFoundException e) {
    
    
 System.out.println("所需文件不存在!");
 } catch (IOException e) {
    
    
 System.out.println("文件读写错误!");
 }
 }
 public static void readFile(String fileName) throws FileNotFoundException,IOException {
    
    
 FileReader in = new FileReader(fileName);
 int tem = 0;
 try {
    
    
 tem = in.read();
 while (tem != -1) {
    
    
 System.out.print((char) tem);
 tem = in.read();
 }
 } finally {
    
    
 if(in!=null) {
    
    
 in.close();
 }
 }
 }
}

Precautions

⭐	方法重写中声明异常原则:子类重写父类方法时,如果父类方法有声明异常,那么子类声明的异常范围不能超过父类声明的范围。

try-with-resource automatically closes the resources of the AutoClosable interface

In JAVA, the garbage collection mechanism of the JVM can automatically recycle internal resources, which brings great convenience to developers. However, JVM's references to external resources (resources that call the underlying operating system), such as database connections, network connections, and input and output IO streams, cannot be automatically recycled. These connections need to be closed manually, otherwise it will cause external resource leakage, connection pool overflow, and abnormal file occupation.

After JDK7, "try-with-resource" was added. It can automatically close the class that implements the AutoClosable interface, and the implementing class needs to implement the close() method. "try-with-resources
statement" simplifies try-catch-finally to try-catch, which is actually a kind of syntactic sugar, and it will still be converted into a try-catch-finally statement at compile time.

package oldwang;
import java.io.FileReader;
public class Test8 {
    
    
 public static void main(String[ ] args) {
    
    
 try(FileReader reader = new FileReader("d:/a.txt");) {
    
    
 char c = (char) reader.read();
 char c2 = (char) reader.read();
 System.out.println("" + c + c2);
 } catch (Exception e) {
    
    
 e.printStackTrace();
 }
 }
}

custom exception

⭐	在程序中,可能会遇到 JDK 提供的任何标准异常类都无法充分描述清楚我们想要表达的问题,这种情况下可以创建自己的异常类,即自定义异常类。
⭐	自定义异常类只需从 Exception 类或者它的子类派生一个子类即可。
⭐	自定义异常类如果继承 Exception 类,则为 CheckedException 异常,必须对其进行处理;如果不想处理,可以让自定义异常类继承运行时异常RuntimeException 类。
⭐	习惯上,自定义异常类应该包含 2 个构造器:一个是默认的构造器,另一个是带有详细信息的构造器。

[Example] Custom exception class

/**IllegalAgeException:非法年龄异常,继承 Exception 类*/
public class IllegalAgeException extends Exception {
    
    
//默认构造器
public IllegalAgeException() {
    
    
}
//带有详细信息的构造器,信息存储在 message 中
public IllegalAgeException(String message) {
    
    
super(message);
}
}

[Example] Use of custom exception classes

class Person {
    
    
private String name;
private int age;
public void setName(String name) {
    
    
this.name = name;
}
public void setAge(int age) throws IllegalAgeException {
    
    
if (age < 0) {
    
    
throw new IllegalAgeException("人的年龄不应该为负数");
 }
this.age = age;
}
public String toString() {
    
    
return "name is " + name + " and age is " + age;
}
}
public class TestMyException {
    
    
public static void main(String[ ] args) {
    
    
Person p = new Person();
try {
    
    
p.setName("Lincoln");
p.setAge(-1);
} catch (IllegalAgeException e) {
    
    
e.printStackTrace();
}
System.out.println(p);
}
}

The execution result is as follows:
insert image description here

Recommendations for using the exception mechanism

⭐	要避免使用异常处理代替错误处理,这样会降低程序的清晰性,并且效率低下。
⭐	处理异常不可以代替简单测试---只在异常情况下使用异常机制。
⭐	不要进行小粒度的异常处理---应该将整个任务包装在一个 try 语句块中。
⭐	异常往往在高层处理 。

⭐ How to use Baidu to solve abnormal problems

insert image description here

In normal learning and development, we often encounter various exceptions. When encountering an exception, you need to follow the following four steps to solve it:

⭐	细心查看异常信息,确定异常种类和相关 Java 代码行号
⭐	确定上下文相关的一些关键词信息(疑难问题,需要)。拷贝异常信息到百度,查看相关帖子,寻找解决思路;
⭐	前两步无法搞定,再问同学/老师或同事;
⭐	前三步无法搞定,请示领导。

Many students panic as soon as they encounter an abnormality, and immediately start asking others for help, but they don't know that there are two major disadvantages in doing so. First, disrespecting others too much and treating others as coolies. Second, you lose the opportunity to improve yourself. Solving an anomaly by yourself means having the ability to solve a class of anomalies. Solving a class of anomalies can greatly improve one's abilities.
Don't be afraid to spend time solving problems, and don't feel that solving problems is a waste of time. In the process of solving the problem, you are also thinking.

Baidu Super Search:

The key to a good Baidu/Google search is to confirm keywords and ask questions correctly.

⭐	寻找问题本身的关键词(名词)
⭐	寻找问题上下文的关键词(名词)
⭐	尽量细致的描述问题,开始搜索
⭐	如果没找到,慢慢减少关键词,扩大搜索范围。

⭐ IDEA debugging debug

insert image description here

At the heart of debugging are breakpoints. When the program execution reaches the breakpoint, it temporarily suspends and stops execution. Just like watching a video and pressing stop, we can watch every detail of the stop in detail.

breakpoint breakpoint

The program runs here, temporarily suspends, and stops executing. We can observe the operation of the program in detail at this time, so as to make further judgments.

  1. Set a breakpoint:
    (1) Click behind the line number to add a breakpoint
    insert image description here

(2) Click again on the breakpoint to cancel the breakpoint

Enter debug view

We can enter the debug view in the following three ways:
(1) Click the button on the toolbar:insert image description here

(2) Right-click the editing area, click: debug

After entering the debug view, the layout is as follows:
insert image description here

On the left is "browse frame":
the debugger lists the methods that the current thread is running at the breakpoint, and each method corresponds to a "stack frame". The top one is the method where the current breakpoint is located.

Variable value observation area:

The debugger lists the variable values ​​associated with the method at the breakpoint. We can use it to view changes in the value of variables.

Debug operation area
insert image description here

We use the buttons in the above figure to perform debugging operations, and their meanings are as follows:
insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/Wwd631255/article/details/131194660