异常总结。

1.异常相关简介

异常是java提供的一种识别和响应错误的一致性机制。

avater

从上图可以看出,所有的异常都是由Throwable继承而来的,它是所有异常的祖先。

Throwable有两个子类,Error和Exception

  • Error是错误,编译错误和系统错误都是通过error抛出的,这个错误一般发生在虚拟机本身,或者在虚拟机试图执行任务的时候,比如:系统崩溃、内存不足、堆栈溢出等,编译器不会对这类错误进行检测,java的应用程序也不会对其进行捕获,这类错误一旦发生,程序直接终止
  • Exception又分为Checked Exception和RuntimeException。
  • Checked Exception是指受查异常,除了运行异常以外都是被检查异常,比如IOException。java编译器会检查它,此类异常,要么通过throws进行声明抛出,要么通过try-catch进行捕获处理,否则不能通过编译。被检查异常通常是可以恢复的。
  • 而RuntimeException是运行时异常,是指那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。编译器不会检查RuntimeException异常。这种异常是运行时发生,无法预先捕捉处理的。如果代码会产生RuntimeException异常,则需要通过修改代码进行避免。

常见的运行时异常:

  • 除数为0之类的算术异常ArithmeticException
  • 数组越界IndexOutOfBoundsException
  • 类文件未找到异常 ClassNotFoundException
  • 空指针异常NullPointerException
  • 操作数据库异常SQLException
2.怎么处理异常

Java异常机制用到的几个关键字:try、catch、finally、throw、throws。

其中:try-catch,try用来监听,将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。catch用来捕获try代码块中的异常。

finally语句块总是会被执行,用来释放之前获取的资源,所以无论发不发生异常,finally都会执行。finally块执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。

throw用来抛出异常,throws用在方法签名中,用于声明该方法可能抛出的异常。

public class Main {
    public static void main(String[] args) {
        try {
        } catch (Exception e) {
        }finally{
        }
    }
}

第二种方法是……直接抛出去,不处理。

虽然有点粗暴,但是有些异常我们没办法处理,只能抛出去,让能解决的人去解决(谁调用谁解决= =。

方法:method declaration的时候加上throws

public class Test{
    //受检查异常的抛出,调用的时候需要try-catch处理异常/抛出
    private static void throwException() throws Exception{
        throw new Exception("Exception");
    }
    //运行时异常的抛出,调用时不会让你处理异常
    private static void throwRuntimeException(){
        throw new RuntimeException("RuntimeException");
    }
}

可以好几个catch来分开处理不同的异常。

try {
   //doing something
} catch (Exception1 e) {
	// handle the first type exception
    System.out.println("Exception1 happened")
} catch (Exception2 f){
	// handle the first type exception
    System.out.println("Exception2 happened")
}

一个exception发生之后,如果是Exception1类型的,就会被第一个handle,如果不是Exception1类型的就会接着往下找catch,如果是Exception2类型的,就会被第二个catch块handle。

在网上找到一个很有意思的:

//m1抛出了一个异常
void m1 throws FileNotFoundException(){
	//大概是想读一些文件,又不想考虑如果文件找不到咋整。(甩锅)
}
//m2调用了m1,相当于从m1手里接到了这个异常,自己不处理,继续往外甩。
void m2 throws FileNotFoundException(){
	m1();//想用m1方法,m1声明如果想用我就要考虑文件找不到的情况。
	//但是m2依然不想考虑文件找不到咋整。
}

该博主给的一个综合的例子:

import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
public class ReadFileTest {
   public static void main(String args[]) {
   		getFile1();
   		System.out.println("=============");
        try{
           // 因为getFile2又把exception甩出来了,所以main方法得处理它。
           getFile2();
        }catch(FileNotFoundException e){
           System.out.println("Exception handled in main");
        }
      
   }
   //getFile1选择了自己处理,不麻烦调用它的方法
   public static void getFile1() {
		try{
   	   		File file = new File("file.txt");
       		FileReader fr = new FileReader(file);
       	}catch(FileNotFoundException e){
       		System.out.println("Exception handled in getfile1");
       }
   }
   //getFile2选择了不处理,继续throws
   public static void getFile2() throws FileNotFoundException{
   	   File file = new File("file.txt");
       FileReader fr = new FileReader(file);
   }
}

运行结果:

Exception handled in getfile1
=============
Exception handled in main

= =一般来讲,所有的exception到了main方法这里都应该已经被解决了。不过好像main方法也可以不解决往外抛出异常……(我凑!


本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

信息论编码实验总结 上一篇
Servlet基本操作 下一篇