Java异常详解

异常(Exception)

  1. Java 中的异常分为两大类:
    a) Checked exception (非 Runtime Exception)
    b) Unchecked exception(Runtime Exception)
  2. Java 中所有的异常类都会直接或间接地继承自 Exception。
  3. RuntimeException 类也是直接继承自 Exception 类,它叫做运行时异常, Java 中所有
    的运行时异常都会直接或间接地继承自 RuntimeException。
  4. Java 中凡是继承自 Exception 而不是继承自 RuntimeException 的类都是非运行时异
    常。
    异常处理的一般结构是:
try{ }
catch(Exception e){ }
finally{ }

无论程序是否出现异常, finally 块中的代码都是会被执行的。
只有try,catch可以,有try,finally也可以,但是光有catch,finally不可以,并且try中可以有多个catch,但是只有一个catch会执行

package Seventieth.Secound;

public class ExceptionTest {
    public static void main(String[] args) {

        int c = 0;
        try{
            int a = 3;
            int b = 0;
            c = a/b;
            System.out.println("hello world");
        }
        catch(ArithmeticException e){
            e.printStackTrace();
        }
        finally {//无论发不发生异常finally都会被执行
            System.out.println("welcome");
        }
        System.out.println(c);
    }
}

结果是:
java.lang.ArithmeticException: / by zero
at Seventieth.Secound.ExceptionTest.main(ExceptionTest.java:10)
welcome
0

  1. 对于非运行时异常(checked exception),必须要对其进行处理,处理方式有两种:
    第一种是使用 try… catch…finally 进行捕获;第二种是在调用该会产生异常的方法所在
    的方法声明 throws Exception
package Seventieth.Third;

public class ExcaptionTest2 {

    public void method() throws Exception{//告诉其他方法我会抛出异常,真正生成异常是在方法里面
        System.out.println("hello world");

        throw new Exception();//生成异常对象,并抛出
    }

    public static void main(String[] args){
        ExcaptionTest2 test = new ExcaptionTest2();

        try{
            test.method();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            System.out.println("aaa");
        }
    }
}

或者是

public static void main(String[] args) throws Exception{
        ExcaptionTest2 test = new ExcaptionTest2();
        
        test.method();//抛出Exception异常
    }

结果是:
hello world
java.lang.Exception
at Seventieth.Third.ExcaptionTest2.method(ExcaptionTest2.java:8)
at Seventieth.Third.ExcaptionTest2.main(ExcaptionTest2.java:15)
aaa

如果main方法再往外抛出就抛给了Java虚拟机了。

  1. 对于运行时异常(runtime exception),我们可以不对其进行处理,也可以对其进行处理。推荐不对其进行处理
  2. NullPointerException 是空指针异常, 出现该异常的原因在于某个引用为 null,但你却调用了它的某个方法。这时就会出现该异常。
package Seventieth.Third;

public class ExceptionTest3 {
    public static void main(String[] args) {
        String str = null;

        System.out.println(str.length());
    }
}

结果是:
Exception in thread “main” java.lang.NullPointerException
at Seventieth.Third.ExceptionTest3.main(ExceptionTest3.java:7)

自定义异常详解

  1. 所谓自定义异常, 通常就是定义了一个继承自 Exception 类的子类, 那么这个类就是一个自定义异常类。 通常情况下,我们都会直接继承自 Exception 类, 一般不会继承某个运行时的异常类。
package Seventieth.Fourth;

public class ExceptionTest4 {

    public void method(String str) throws MyException{//这里可以抛出Exception,但是在catch中也要写Exception
        if(str == null){
            throw new MyException("传入的字符串参数不能为null");
        }
        else{
            System.out.println(str);
        }

    }

    /*public static void main(String[] args) throws MyException{
        ExceptionTest4 test = new ExceptionTest4();

        test.method(null);
        System.out.println("此处不会被执行");
    }
    //如果选择这种方式,程序在异常处终止
    执行结果
    Exception in thread "main" Seventieth.Fourth.MyException: 传入的字符串参数不能为null
	at Seventieth.Fourth.ExceptionTest4.method(ExceptionTest4.java:7)
	at Seventieth.Fourth.ExceptionTest4.main(ExceptionTest4.java:18)
    */

    public static void main(String[] args) {
        try {
            ExceptionTest4 test = new ExceptionTest4();

            test.method(null);
        } catch (MyException e) {//但是如果method抛出的是MyException也可以用Exception(多态)
            e.printStackTrace();
        }
        finally {
            System.out.println("异常处理完毕");
        }

        System.out.println("程序执行完毕");
    }
    //执行异常后继续往下执行
}

结果是:
Seventieth.Fourth.MyException: 传入的字符串参数不能为null
at Seventieth.Fourth.ExceptionTest4.method(ExceptionTest4.java:7)
at Seventieth.Fourth.ExceptionTest4.main(ExceptionTest4.java:25)
异常处理完毕
程序执行完毕

加入第二个异常

package Seventieth.Fifth;

public class MyException2 extends Exception{

    public MyException2() {
        super();
    }

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

}

```ExceptionTest4
将ExceptionTest4改写如下
```java
package Seventieth.Fifth;

import Seventieth.Fourth.MyException;

public class ExceptionTest4 {

    public void method(String str) throws MyException, MyException2{//这里可以抛出Exception,但是在catch中也要写Exception
        if(str == null){
            throw new MyException("传入的字符串参数不能为null");
        }
        else if("hello".equals(str)){
            throw new MyException2("传入的字符串不能为hello");
        }
        else{
            System.out.println(str);
        }

    }


    public static void main(String[] args) {
        try {
            ExceptionTest4 test = new ExceptionTest4();

            test.method("hello");
        } catch (MyException e) {//但是如果method抛出的是MyException也可以用Exception(多态)
            System.out.println("进入到MyException catch块");
            e.printStackTrace();
        }
        catch (MyException2 e){
            System.out.println("进入到MyException2 catch块");
            e.printStackTrace();
        }
        finally {
            System.out.println("异常处理完毕");
        }

        System.out.println("程序执行完毕");
    }
    //执行异常后继续往下执行
}

结果是:
进入到MyException2 catch块
Seventieth.Fifth.MyException2: 传入的字符串不能为hello
at Seventieth.Fifth.ExceptionTest4.method(ExceptionTest4.java:12)
at Seventieth.Fifth.ExceptionTest4.main(ExceptionTest4.java:25)
异常处理完毕
程序执行完毕

如果将method方法抛出的异常改为Exception(必须要是所有创建异常的父类,否则不可以这样写),那么在下列的try catch中必须加如一个Exception的catch(虽然他永远不会被执行),但是如果把MyException的catch删掉,也不会错,这样MyException的异常会进入Exception的catch块中进行,又但是,如果把Exception的catch块放在MyException块的上面那么MyException和MyException2两个的catch块永远不会被执行了所以==这种形式是不被允许的。==会报出Exception ‘Seventieth.Fourth.MyException’ has already been caught的错误

package Seventieth.Fifth;

import Seventieth.Fourth.MyException;

public class ExceptionTest4 {

    public void method(String str) throws Exception{//这里可以抛出Exception,但是在catch中也要写Exception
        if(str == null){
            throw new MyException("传入的字符串参数不能为null");
        }
        else if("hello".equals(str)){
            throw new MyException2("传入的字符串不能为hello");
        }
        else{
            System.out.println(str);
        }

    }

    public static void main(String[] args) {
        try {
            ExceptionTest4 test = new ExceptionTest4();

            test.method("hello");
        } catch (MyException e) {//但是如果method抛出的是MyException也可以用Exception(多态)
            System.out.println("进入到MyException catch块");
            e.printStackTrace();
        }
        catch (MyException2 e){
            System.out.println("进入到MyException2 catch块");
            e.printStackTrace();
        }
        catch (Exception e){
            System.out.println("进入到Exception catch块");
            e.printStackTrace();
        }
        finally {
            System.out.println("异常处理完毕");
        }

        System.out.println("程序执行完毕");
    }
    //执行异常后继续往下执行
}

结果是:
进入到MyException2 catch块
Seventieth.Fifth.MyException2: 传入的字符串不能为hello
at Seventieth.Fifth.ExceptionTest4.method(ExceptionTest4.java:12)
at Seventieth.Fifth.ExceptionTest4.main(ExceptionTest4.java:25)
异常处理完毕
程序执行完毕

  1. 我们可以使用多个 catch 块来捕获异常,这时需要将父类型的 catch 块放到子类型的catch 块之后,这样才能保证后续的 catch 可能被执行,否则子类型的 catch 将永远无法到达,Java 编译器会报编译错误;如果多个 catch 块的异常类型是独立的(MyException, MyException2), 那么谁前谁后都是可以的。
  2. 如果 try 块中存在 return 语句,那么首先也需要将 finally 块中的代码执行完毕,然
    后方法再返回。
package Seventieth.Fourth;

public class ExceptionTest5 {
    public void method(){
        try {
            System.out.println("进入到try块");
            return;
        } catch (Exception e) {
            System.out.println("异常发生了");
        }
        finally {
            System.out.println("进入到finally块");
        }

        System.out.println("异常处理后续的代码");
    }

    public static void main(String[] args) {
        ExceptionTest5 test = new ExceptionTest5();
        test.method();

    }

}

结果是:
进入到try块
进入到finally块

  1. 如果 try 块中存在 System.exit(0)语句,那么就不会执行 finally 块中的代码, 因为
    System.exit(0)会终止当前运行的 Java 虚拟机,程序会在虚拟机终止前结束执行。
package Seventieth.Fourth;

public class ExceptionTest5 {
    public void method(){
        try {
            System.out.println("进入到try块");
            System.exit(0);
        } catch (Exception e) {
            System.out.println("异常发生了");
        }
        finally {
            System.out.println("进入到finally块");
        }

        System.out.println("异常处理后续的代码");
    }

    public static void main(String[] args) {
        ExceptionTest5 test = new ExceptionTest5();
        test.method();

    }

}

结果是:
进入到try块

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值