Java 异常从精通到陌生

Java 异常从精通到陌生

一.什么的异常?

异常(不同于寻常的)指的是在程序运行过程中发生的异常事件,通常是由外部问题(如硬件错误、输入错误)所导致的。在Java等面向对象的编程语言中异常属于对象。

在Java中通过Throwable类的各种子类来描述不同的异常。

二.为什么使用异常机制

  • 可读性
  • 可靠性
  • 可维护性

三.Java异常层次结构

Java 异常从精通到陌生_第1张图片

Throwable

Throwable 是 Java 语言中所有错误与异常的超类。表示任何可以作为异常被抛出的类。

Error

编译时和系统错误,程序中无法处理。

Exception

程序本身可以捕获并且可以处理的异常。

  • RuntimeException

四.使用

声明 throws

用于声明改方法可能抛出异常

public  void throwsException() throws IOException{
     
   
}

抛出 throw

public  void throwsException() throws IOException {
     
       throw new IOException();
}

捕获 catch

catch 语句块中可以捕获多个异常类型,并对不同类型的异常做出不同的处理

public void catchException(){
     
    try {
     
        throwsException();
    } catch (IOException e) {
      
        //如果不处理可以声明异常继续抛出
        e.printStackTrace(); 
    }catch (Exception e) {
      
        e.printStackTrace(); 
    }
}

同一个 catch 也可以捕获多种类型异常,用 | 隔开

public void catchException(){
     
    try {
     
        throwsException();
    } catch (IOException | Exception e) {
      
        //如果不处理可以声明异常继续抛出
        e.printStackTrace(); 
    }
}

最后 finally

finally用于将资源恢复到它们的初始状态。如:以打开的文件或者网络链接

public void BufferedWriter() {
     
    final File file = new File("C:/Users/TheBlindM/Desktop/gbk.txt");
    FileWriter fileWriter =null; 
    PrintWriter printWriter = null;
    try  {
     
        fileWriter = new FileWriter(file);
        printWriter = new PrintWriter(fileWriter);
        while (true) {
     
            printWriter.println("hhh");
            printWriter.flush();
        }

    } catch (IOException e) {
     
        e.printStackTrace();
    }finally {
     
        if(fileWriter!=null) {
     
            try {
     
                fileWriter.close();
            } catch (IOException e) {
     
                e.printStackTrace();
            }
        }
        if (printWriter!=null){
     
            printWriter.close();
        }
            
    }

}

finally总是被执行(不过凡事都有例外) 。

finally遇见如下情况不会执行

  • 在前面的代码中用了System.exit()退出程序。
  • finally语句块中发生了异常。
  • 程序所在的线程死亡。
  • 关闭CPU。

try-finally可直接使用

finally内部不建议写return,会覆盖原先的return

try-with-resource

try-with-resource是Java 7中引入的

JAVA 7 提供了更优雅的方式来实现资源的自动释放,自动释放的资源需要是实现了 AutoCloseable 接口的类。

public void BufferedWriter() {
	final File file = new File("C:/Users/TheBlindM/Desktop/gbk.txt");
	try (FileWriter fileWriter = new FileWriter(file); 
	     final PrintWriter printWriter = new PrintWriter(fileWriter);) {
         while (true) {
             printWriter.println("hhh");
             printWriter.flush();
         }
	} catch (IOException e) {
       e.printStackTrace();
	}

}

流程

Java 异常从精通到陌生_第2张图片

五.实现机制

异常表

行号
20  public static int throwException() {
     
21  	int x;
22  	try {
     
23  		x=1;
24  		return x;
25  	}catch (Exception e){
     
26  		x=2;
27  		return x;
28  	}finally {
     
29  	 	x=3;
30     	}
31  }
  public static int throwException();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=4, args_size=0
         0: iconst_1 //1(int)值入栈。 对应23行 x=1
         1: istore_0 //将栈顶int类型值保存到局部变量0中。
         2: iload_0  //从局部变量0中装载int类型值入栈。 对应24行
         3: istore_1
         4: iconst_3 //3(int)值入栈。 对应23行 x=1
         5: istore_0
         6: iload_1 //从局部变量1中装载int类型值入栈。 值为1
         7: ireturn
         8: astore_1 // 将栈顶引用类型值保存到局部变量1中。
         9: iconst_2 //2(int)值入栈。 对应26行 x=2
        10: istore_0 //将栈顶int类型值保存到局部变量0中
        11: iload_0  //从局部变量0中装载int类型值入栈。 对应27行
        12: istore_2 //
        13: iconst_3 
        14: istore_0 //
        15: iload_2
        16: ireturn 
        17: astore_3 //将栈顶引用类型值保存到局部变量3中。
        18: iconst_3 //1(int)值入栈。 对应27行 x=1
        19: istore_0
        20: aload_3
        21: athrow
      Exception table:
         from    to  target type
             0     4     8   Class java/lang/Exception
             0     4    17   any
             8    13    17   any

Exception table:异常表

  • from 可能会发生异常的起点
  • to 可能会发生异常的结束点
  • target from to之间发生异常后处理的位置
  • type 可以处理的类型

3条异常表对应三条

  • 如果try语句块中出现属于Exception或其子类的异常,则转到catch语句处理
  • 如果try语句块中出现不属于Exception或其子类的异常,则转到finally语句处理
  • 如果catch语句块中出现异常,则转到finally语句处理

问题:

1.如果finally中带return或者catch中带return,会怎样?

如果带return 在字节码中会转化为ireturn(返回int类型值,返回栈顶)

六.编写建议

1.异常应该用于异常的情况下,永远不要应该用于正常的控制流程

2.对于可恢复的情况使用受检异常,对于编程错误使用运行时异常

3. 优先使用标准异常

异常 使用场合
IllegalArgumentException 参数的值不合适
IllegalStateException 参数的状态不合适
NullPointerException 在null被禁止的情况下参数值为null
IndexOutOfBoundsException 下标越界
ConcurrentModificationException 在禁止并发修改的情况下,对象检测到并发修改
UnsupportedOperationException 对象不支持客户请求的方法

4.优先捕获最具体的异常

5.不要记录并抛出异常

欢迎关注公众号
Java 异常从精通到陌生_第3张图片
参考
深入理解JVM虚拟机
Effective Java
https://www.pdai.tech/md/java/basic/java-basic-x-exception.html

你可能感兴趣的:(Java,异常,try,catch,try-resource)