【Java异常】干净明了的Java“异常”机制详解

异常,即不正常,我们的代码出现的编译或者运行时的错误。本文,将带你了解Java的异常机制的基础语法,为以后的学习和开发打好基础。

异常体系结构

Throwable 类是 Java 语言中所有错误或异常的超类。其下主要分为两种类型:Error、Exception。

辨析错误(Error)和异常(Exception):
Error:程序在运行期间发生了某种错误(XxxError),Error错误通常没有具体的处理方式,程序将会结束运行。Error错误的发生往往都是系统级别的问题,都是jvm所在系统发生的,并反馈给jvm的。我们无法针对处理,只能修正代码。
Exception:指程序在编译、运行期间发生了某种异常(XxxException),我们可以对异常进行具体的处理。若不处理异常,程序将会结束运行。所有的异常类是从 java.lang.Exception 类继承的子类。其有两个主要的子类:IOException 类和 RuntimeException 类。

类比理解:
在这里插入图片描述

用代码理解Error和Exception:

// 异常的产生演示如下:
public static void main(String[] args) {
	int[] arr = new int[3];
	System.out.println(arr[0]);
	System.out.println(arr[3]);
// 该句运行时发生了数组索引越界异常ArrayIndexOutOfBoundsException,由于没有处理异常,导致程序无法继续执行,程序结束。
	System.out.println("over"); // 由于上面代码发生了异常,此句代码不会执行
}

// 错误的产生演示如下:
public static void main(String[] args) {
int[] arr = new int[1024*1024*100];
//该句运行时发生了内存溢出错误OutOfMemoryError,开辟了过大的数组空间,导致JVM在分配数组空间时超出了JVM内存空间,直接发生错误。
}

throwable类

方法:

  1. String getMessage() 对异常信息的详细描述
  2. String toString() 对异常信息的简短描述
  3. void printStackTrace() 将异常信息追踪到标准的错误流

使用示例:

public class ExceptionDemo4 {
	public static void main(String[] args) {
		method();
	}

	private static void method() {
		try {
			System.out.println(2 / 0);
		} catch(ArithmeticException e) {
			//String getMessage() : 异常原因
			System.out.println(e.getMessage());
			
			//String toString(): 异常类型和原因
			System.out.println(e.toString());

			//void printStackTrace(): 异常类型原因和位置
			e.printStackTrace();
		}
	}
}

编译时期异常

定义:

  1. 编译期间就检查异常是否发生,如果有异常,则编译不通过;

体系结构:
在这里插入图片描述

快速理解编译时异常

public class Main {
	public static void main(String[] args) throws Exception { //本方法也没有处理异常,只能继续向外抛
		function(); //调用该方法,就要处理该方法的异常
	}
	public static void function() throws Exception { //本方法没有(或没有能力)处理异常
		throw new Exception(); //产生、制造异常
	}
}

特性:
程序语法正确,但因为外在的环境条件不满足引发。例如:用户错误及I/O问题,程序试图打开一个并不存在的远程Socket端口。这不是程序本身的逻辑错误,而很可能是远程机器名字错误(用户拼写错误)。对商用软件系统,程序开发者必须考虑并处理这个问题。Java编译器强制要求处理这类异常,如果不捕获这类异常,程序将不能被编译。

常见编译时异常:
SQLException
IOexception
FileNotFoundException
ClassNotFoundException
EOFException
IllegaArguementException

运行时期异常

定义:

  1. 运行时期才检查程序是否有异常,有异常则程序终止。

快速理解运行时异常

public class Main {
	public static void main(String[] args) {
		function();
	}
	public static void function() {
		throw new RuntimeException(); //产生、制造异常,运行时异常不用向外抛
	}
}

体系结构:
在这里插入图片描述

特性:

  1. 是哪些可能在Java虚拟机正常运行期间抛出的异常的超类。
  2. 方法内部抛出的异常时运行异常(throw new XxxException),那么在方法的申明上,不需要throws语句。这样设计的原因可能是:运行时异常一般是不会发生的,如果发生了,需要程序员停止程序并修改源代码。
  3. 这意味着程序存在bug,如数组越界,0被除,入参不满足规范…这类异常需要更改程序来避免,Java编译器强制要求处理这类异常。

常见运行时异常:
StringIndexOutOfBoundsException、
ArrayIndexOutOfBoundsException、
ArithmeticException、
IllegaArguementException、
NullPointException

异常的处理

在开发中,建议使用“try…catch….finallay”,自己检测和捕获异常;而不建议使用“throw、throws”向外抛出异常。

异常的捕获和处理

异常的捕获和处理的三种方式

1try……catch……
try{
	可能出现异常的代码块;
}catch(异常类型){
	处理异常的代码块;
}

2、多个catch……

try{
	可能出现异常的代码块;
}catch(异常类型){
	处理异常的代码块;
}catch(异常类型){
	处理异常的代码块;
}

多个catch的顺序:平级之间没有顺序关系,如果有子父类,父类异常必须放在后面

3、try……catch……finally……

try{
	可能出现异常的代码块;
}catch(异常类型){
	处理异常的代码块;
}catch(异常类型){
	处理异常的代码块;
}finally{
    代码块: 不管你try代码块里面的内容是否有异常,我finally代码中的内容都会被执行。往往用做释放资源的事情
}

try-catch

法则:
try 代码后不能既没 catch 块也没 finally 块。

初次尝试

public class Main {
	// 快速理解try-catch
	private static void method() {
		try {
			String s = null;
			System.out.println(s.length());
		} catch (NullPointerException e) {
			System.out.println("出现空指针了");
		}

		try {
			int[] arr = new int[5];
			System.out.println(arr[8]);
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("出现数组越界了");
		}
	}

	// 优化以上的异常处理
	public static void method02() {
		try {
			String s = null;
			System.out.println(s.length());
		} catch (ArrayIndexOutOfBoundsException e) { //具体的异常
			System.out.println("出现数组越界了");
		} catch (NullPointerException e) {
			System.out.println("出现空指针了");
		} catch (Exception e) { //Exception可以接收任何类型的异常
			System.out.println("出现异常了");
		}
	}

	public static void main(String[] args) {
		method();
		// method02();
	}
}

try-catch-finally

快速理解使用方式

import java.io.FileWriter;
import java.io.IOException;

public class Main {
	public static void main(String[] args) {
		method();
	}

	public static void method() {
		FileWriter fw = null;
		try {
			System.out.println(2 / 0); //try中一旦发生异常,其后的代码将不会再执行,直接跳转到catch语句开始执行;
			fw = new FileWriter("a.txt");
			fw.write("hello");
			fw.write("world");
			//System.out.println(2 / 0);
			fw.write("java");
			
			//fw.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			//释放资源
			try {
				if(fw != null) {
					fw.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

异常的抛出

当我们不想处理异常,或者没有能力处理的时候,我们可以选择抛出异常,谁调用方法谁处理异常。

throw 与throws两个关键字:

  1. throw关键字是用于方法内部的,throws是用于方法声明上的。
  2. throw关键字是用于方法内部抛出一个异常对象的,throws关键字是用于在方法声明上声明抛出异常类型的。
  3. throw关键字后面只能有一个异常对象,throws后面一次可以声明抛出多种类型的异常。

throw和throws在功能上的区别:

  1. throws:处理异常的方式,是在本方法不能够处理才向外抛,由调用者处理该异常;
  2. throw:制造异常的方式,是开发者注意到某句代码可能发生异常,而主动向外抛的异常方式。throw后面必须是“new 一个异常类”,这个异常类必须是Exception或者其子类。
  3. 注意:如果抛出(throw)的是编译时期异常,必须在方法声明处抛出(throws);

快速理解throw和throws

public class Main {
	public static void main(String[] args) {
		int[] arr = null;
		int i = getArray(arr);
		System.out.println(i);
	}
	public static int getArray(int[] arr) {
		int i = arr[arr.length-1]; //发生异常语句
		return i*2;
	}
}
/* 发生异常:
Exception in thread "main" java.lang.NullPointerException
	at Main.getArray(Main.java:12)
	at Main.main(Main.java:8)
*/


public class Main {
	public static void main(String[] args) throws Exception { //抛出异常,main方法抛出的异常由JVM处理
		int[] arr = null;
		int i = getArray(arr);
		System.out.println(i);
	}
	public static int getArray(int[] arr) throws Exception { //抛出异常
		if(arr == null) {
			throw new Exception("数组不存在,为null"); //抛出异常
		}
		int i = arr[arr.length-1]; //发生异常语句
		return i*2;
	}
}
/*运行结果:
	Exception in thread "main" java.lang.Exception: 数组不存在,为null
	at Main.getArray(Main.java:10)
	at Main.main(Main.java:5)
*/

自定义异常类

写一个类去继承Exception或者RuntimeException,然后实现多个构造即可;

快速理解自定义异常的使用

/* 用自定义异常类实现
 * 写一个方法,接受考试成绩,如果考试成绩在0-100之间则属于正常,否则属于异常
 */
public class Main {
	public static void main(String[] args) {
		try {
			checkScore(110);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void checkScore(int score) throws Exception {
		if(score < 0 || score > 100) {
			throw new MyException("考试成绩不符合要求"); //
		} 
		System.out.println("考试成绩符合要求");
	}
}

//如果继承Exception就是编译时异常,如果继承RuntimeException就是运行时异常;
class MyException extends /*RuntimeException*/ Exception{
	//使用工具直接生成:"source","Generatre xxXx"
	public MyException() {
		super();
	}

	public MyException(String message) {
		super(message);
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值