Web全栈~20.异常机制

Web全栈~20.异常机制

上一期

NullPointerException 空指针异常

public class Test {
     
    public static void main(String[] args) {
     
        String str = null;
        System.out.println(str.charAt(2));
        System.out.println("hello world");
    }
}

Web全栈~20.异常机制_第1张图片

       变量还没有初始化就直接访问charAt(2),因此就报了NullPointerException异常。这个异常我们称之为空指针异常。

       其实底层机制就是,当执行到str.charAt(2)的时候,实际上这个str是没有值的,是null。因此虚拟机没有办法继续执行下去,所以就启动了这个异常机制。

       首先,它会创建一个异常对象,然后查找看谁能处理这个异常,在示例代码中,没有代码能处理这个异常。所以Java就会启动默认处理机制,打印异常信息并且退出程序。

       触发异常之后的代码则不会执行,所以屏幕上也不会看见hello world。

NumberFormatException数字格式异常

       这里举一个例子

public class Test {
     
    public static void main(String[] args) {
     
        String a = "hello";
        int b = Integer.parseInt(a);
        System.out.println(b);
    }
}

Web全栈~20.异常机制_第2张图片

       这里字符串a中并没有包含数字,因此在转换的过程中出现错误,所以出现异常。

捕获异常

       事实上,在程序中,总是难免会出现各种各样的异常这些都是无法预见的。就比如我写了一个计算器,当用户输入2/0这种类似的算式的时候,又会出现异常。但总不能每次都因此而让程序退出,于是Java提供了throw抛异常和try catch捕获异常

public class Test {
     
    public static void main(String[] args) {
     
        try{
     
            int a = 2 / 0;
        }catch (Exception e){
     
            System.out.println("被除数不能为0!");
        }
    }
}

       当try里面的代码块没有出现异常的时候则不会执行catch里面的代码。而当try的代码块出现异常了,虚拟机则会执行catch

finally

       Finally代码不管有没有异常发生它都会执行。

       没有异常发生的时候,在try内的代码执行结束后,执行finally。

       如果发生了异常并且给catch捕获,则在执行完catch之后执行finally。

       如果有异常且未被捕获,则在异常被抛给上层之前执行。

public class Test {
     
    public static void main(String[] args) {
     
        try{
     
            int a = 2 / 0;
        }catch (Exception e){
     
            System.out.println("被除数不能为0!");
        }finally{
     	
			System.out.println("finally已执行!");
		}
    }
}

       事实上,不用try catch也可以直接执行 try finally。那么如果我在try 里面 使用 return 会怎样呢?

代码如下

public class Test {
     
    public static void main(String[] args) {
     
        int result = fun();
        System.out.println("result = " + result);
    }
    public static int fun(){
     
        int ret = 0;
        try{
     
            return ret;
        }finally {
     
            ret = 5;
            System.out.println("ret = " + ret);
        }
    }
}

       测试的结果是,finally里面的代码依然会被执行。但是,虽然给ret赋值了5。但返回的值最终还是0。所以,即使在try里面使用了return,也依然会执行finally。但是finally无法改变return的值。

       因为在执行的过程中, try执行到return,会先把ret的值保存在一个临时变量中,等到finally执行完毕之后才会返回。因此finally无法改变最终的返回结果

       那么,如果我在finally里面也执行一个return呢?结果会怎样?

代码如下

public class Test {
     
    public static void main(String[] args) {
     
        int result = fun();
        System.out.println("result = " + result);
    }
    public static int fun(){
     
        int ret = 0;
        try{
     
            return ret;
        }finally {
     
            ret = 5;
            return ret;
        }
    }
}

       这个时候try里面的return就会丢失。只会执行finally里面的return

异常类体系

Web全栈~20.异常机制_第3张图片

       以Throwable为根,Java定义了很多的异常类表示各种类型的异常。Throwable是所有异常的基类,它的两个之类是Error和Exception

       Error表示系统错误或者资源耗尽,由Java系统自己使用,应用程序不应抛出和处理。

       Exception则表示应用程序错误,它有很多子类。应用程序也可以通过继承Exception或其子类创建自定义异常。

受检异常和未受检异常

       RuntimeException表示的是未受检异常,而Exception的其他子类和它自身都是受检异常。

       受检异常和未受检异常的区别主要是Java如何去处理它们。对于受检异常,Java会强制要求程序员自己进行处理,否则编译错误。而未受检异常则没有这个要求。

       就比如我们定义IO相关类的时候则会要求捕获或者抛出IOException,而这个Exception就属于受检异常。而NullPointerException则属于受检异常,可以抛也可以不抛~

       Java中的众多异常本身都是Exception的子类。之所以定义这么多,其实是为了通过合适的名字,能够更快的让用户知道当前报的是什么异常。

       未受检异常表示编程的逻辑错误,编程时应该检查以避免这些错误,比如空指针异常,如果真的出现了这些异常,程序退出也是正常的,程序员应该检查程序代码的bug而不是想办法处理这种异常。受检异常表示程序本身没问题,但由于I/O、网络、数据库等其他不可预测的错误导致的异常,调用者应该进行适当处理。

       但其实编程错误也是应该进行处理的,尤其是Java被广泛应用于服务器程序中,不能因为一个逻辑错误就使程序退出。所以,目前一种更被认同的观点是:Java中对受检异常和未受检异常的区分是没有太大意义的,可以统一使用未受检异常来代替。

try-with-resouces

       对于一些使用资源的场景,比如文件和数据库连接,典型的使用流程是首先打开资源,最后在finally语句中调用资源的关闭方法,针对这种场景,Java 7开始支持一种新的语法,称之为try-with-resources,这种语法针对实现了java.lang.AutoCloseable接口的对象

public static void function() throws Exception {
     
    try(AutoCloseable r = new FileInputStream("hello")) {
      //创建资源
        //使用资源
    }
}

你可能感兴趣的:(web,java)