何为异常?
在Java中,异常是指破坏程序正常流程的事件。 它是在运行时抛出的对象。
Java中的异常处理是处理运行时错误的强大机制之一,这样就可以维护应用程序的正常流程。
异常类的层次结构
Error 和 Exception
Error
Error类以及他的子类的实例,代表了JVM本身的错误。错误不能被程序员通过代码处理。
Exception
Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用,是异常处理的核心。
checked exception(受查异常) 和 unchecked exception(非受查异常)
checked exception
除了Error 和 RuntimeException的其它异常。受查异常会在编译时被检测。如果一个方法中的代码会抛出受查异常,则该方法必须包含异常处理,即 try-catch 代码块,或在方法签名中用 throws 关键字声明该方法可能会抛出的受查异常,否则编译无法通过。
uncheck exception
Error 和 RuntimeException 以及他们的子类。非受查异常不会在编译时被检测。
Java Exception 关键字:
Keyword | Descrption |
---|---|
try | 关键字“try”用于指定一个块,在其中放置可能发生异常的代码。try块后面必须跟catch或finally。这意味着,我们不能单独使用try块。 |
catch | “catch”块用于处理异常。它之前必须有try块,这意味着我们不能单独使用catch块。后面可以跟finally块。 |
finally | “finally”块用于执行程序的重要代码。finally语句块总是会被执行。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止 |
throw | 用于抛出异常 |
throws | 关键字"throws"用于声明异常。它不会抛出异常。它表明方法中可能发生异常。它总是与方法签名一起使用。 |
try 块
try块用于包含可能抛出异常的代码。它必须在方法中使用
如果在try块中的特定语句发生异常,则块代码的其余部分将不会执行。因此,建议不要将不会抛出异常的代码保存在try块中
语法:
try{
//code that may throw an exception
}catch(Exception_class_Name ref){}
try{
//code that may throw an exception
}finally{}
try{
//code that may throw an exception
}catch(Exception_class_Name ref){
}finally{
}
catch 块
catch块通过在参数中声明异常类型来处理异常。声明的异常的父类必须是Exception。
catch块只能在try块之后使用。 您可以将多个catch块与单个try块一起使用。
多catch 块
一个try块之后可以是一个或多个catch块。 每个catch块必须包含一个不同的异常处理程序。 因此,如果需要在发生不同的异常时执行不同的任务,可以使用多catch块。
tips:
- 一次只发生一个异常,一次只执行一个catch块
- 必须将所有catch块从最具体到最一般的顺序进行排序,即,对于ArithmeticException的catch必须先于对Exception的catch。
public class MultipleCatchBlock {
public static void main(String[] args) {
try{
int a[]=new int[5];
a[5]=30/0;
}
catch(ArithmeticException e)
{
System.out.println("Arithmetic Exception occurs");
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("ArrayIndexOutOfBounds Exception occurs");
}
catch(Exception e)
{
System.out.println("Parent Exception occurs");
}
System.out.println("rest of the code");
}
}
output:
Arithmetic Exception occurs
rest of the code
finally 块
Java finally 块是一个用于执行重要代码的块,如关闭连接、流等
无论异常是否被处理,Java finally块总是会被执行
tips:
- 对于每个try块,可以有0个或多个catch块,但只有一个finally块
示例:
public class FinallyTest {
public static void main(String[] args) {
try {
int i = 50/0;
}catch (Exception e){
System.out.println(e);
}finally {
System.out.println("finally block is always be executed");
}
System.out.println("rest of the code");
}
}
final,finally,finalize之间的区别
No. | final | finally | finalize |
---|---|---|---|
1 | Final用于对类、方法和变量进行限。Final类不能被继承,Final方法不能被重写,Final变量值不能被更改 | Finally是异常处理机制的关键字,用于放置重要代码,无论是否处理异常,都将执行它 | Finalize用于在对象被垃圾收集之前执行清理处理 |
2 | Final 是一个关键字 | Finally 是一个块 | Finalize 是方法 |
throw 关键字
Java throw关键字用于显式地抛出异常且主要用于抛出自定义异常
public class ThrowTest {
public static void validate(int age) {
if (age < 18)
throw new ArithmeticException("not valid");
else
System.out.println("welcome to vote");
}
public static void main(String[] args) {
validate(17);
System.out.println("rest of the code");
}
}
output:
Exception in thread "main" java.lang.ArithmeticException: not valid
throws 关键字
throws关键字用于声明异常。 它向程序员提供了可能发生异常的信息,因此,程序员最好提供异常处理代码,以便可以维持正常流程
tips:
如果您正在调用声明异常的方法,则必须捕获或声明异常
示例1:捕获异常并处理
public class ThrowsTest {
public static void main(String args[]){
try{
M m=new M();
m.method();
}catch(Exception e){System.out.println("exception handled");}
System.out.println("normal flow...");
}
}
class M{
void method()throws IOException{
throw new IOException("device error");
}
}
示例2:声明异常
public class ThrowsTest2 {
public static void main(String args[])throws IOException{//declare exception
N n = new N();
n.method();
System.out.println("normal flow...");
}
}
class N {
void method() throws IOException {
throw new IOException("device error");
}
}
自定义异常
如果要自定义受查异常,那么扩展Exception类即可;如果要自定义非受查异常,那么可以扩展RuntimException。
//自定义受查异常
public class MyException extends Exception { //1. 定义一个继承Exception的类
public MyException() { } //无参构造
public MyException(String message) {
super(message); //2. 调用super方法
}
public MyException(String message, Throwable cause) {
super(message, cause); //message: 异常提示信息,cause: 类型
}
}
class ExceptionTest {
public static void main(String[] args) {
try {
int i = demo(3);
} catch (MyException e) {
e.printStackTrace();
}
}
public static int demo(int index) throws MyException {
int[] arr = {1,2,3};
if (index < 0 || index >= arr.length)
throw new MyException("传递的索引越界");
return arr[index];
}
}
output:
com.dgut.MyException: 传递的索引越界
at com.dgut.ExceptionTest.demo(MyException.java:24)
at com.dgut.ExceptionTest.main(MyException.java:16)