Skip to content

异常

异常

Java中的错误分为两类:

编译时错误

一般指语法错误,这种错误是显而易见的,IDE集成开发环境都会对这种错误进行提示,即我们在编写代码时可以看到的语法错误。

运行时错误

这类错误指我们在编写代码的过程中以及程序编译期间都没有问题,可以正常编译通过,一旦运行就会报错,这类错误容易被忽略,比如数组下标越界,把0当作除数等。

Java作为一门面向对象的编程语言,可以将任何事物看成对象,同理,错误也可以被看做是对象,Java中有一组专门用来描述各种不同的运行错误的类。

异常就是Java提供的用于处理运行时错误的一种机制,具体步骤为当程序出现错误时,会自动生成一个异常类对象,该对象就封装了异常的所有信息并提交给系统,由系统转交给能处理该异常的代码进行处理。

异常类

可以分为两类,Error和Exception

Error

指系统错误,程序无法解决,JVM生成。

Exception

指程序运行期间出现的错误,我们编写的程序可以对其进行处理。

异常的使用

try-catch,用try来监听可能会发生异常的代码,一旦发生异常,系统会自动生成一个异常对象,通过catch捕获该异常对象并进行处理。

基本语法:

try{ //可能会抛出异常的代码 }catch(异常对象){ //处理异常 }

例1:

java
public class Test {
	public static void main(String[] args) {
		try {
			int num = 10/0;
		} catch (Exception e) {
			String message = e.getMessage()
      System.out.println(message)
		}
	}
}

例2:

java
public class Test {
	public static void main(String[] args) {
		try {
			int [] array = {1,2,3};
      System.out.println(array[3])
		} catch (Exception e) {
      // 获取错误信息
			String message = e.getMessage()
      System.out.println(message)
		}
	}
}

例3:

java
public class Test {
	public static void main(String[] args) {
		try {
			Cal cal = new Cal();
			cal.test();
		} catch (Exception e) {
      // 打印错误栈
			e.printStackTrace();
		}
	}
}
java
public class Cal {
	public void test() {
		Tools tools = new Tools();
		tools.test();
	}
}
java
public class Tools {
	public void test() {
		int num = 10/0;
	}
}

finally

除了try-catch,finally关键字也是经常使用的 无论程序是否抛出异常,finally代码块中的程序都会执行,finally一般跟在catch代码块之后, 基本语法: try{ //可能会抛出异常的代码 }catch(异常对象){ //处理异常 }finally{ //无论是否抛出异常都要执行的代码 }

因为finally这种特性(无论如何一定会执行),一般在finally中进行释放资源的操作。

java
public class Test2 {
	public static void main(String[] args) {
		System.out.println(test());
    // 打印结果:
		// finally...
    // 20
	}
	
	public static int test() {
		try {
      int num = 10/0;
			System.out.println("try");
			return 10;
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			System.out.println("finally...");
			return 20;
		}
	}
}

异常类的分级

第一级:Throwable:所有异常类的根结点

第二级:Error和Exception

前两级都在java.lang包中。

第三级:Error中的常见的类:VirtualMachineError,AWTError,IOError等;Exception中常见的类:IOException,RuntimeException等。

VirtualMachineError,StackOverflowError,OutOfMemoryError存在于java.lang包中。 AWTError存在于java.awt包中。 IOError存在于java.io包中。

IOException存在于java .io包中。 RuntimeException存在于java.lang包中。

第四级:

1)VirtualMachineError

VirtualMachineError中常见的类:StackOverflowError,OutOfMemoryError,用来描述内存溢出等系统问题。

2)IOException和RuntimeException
IOException:

FileLockInterruptionException,FileNotFoundException,FilerException,这些异常通常都是处理通过IO流进行文件传输过程中发生的错误。

FileLockInterruptionException存在于java.nio.channels包中。 FileNotFoundException存在于java.io包中。 FilerException存在于javax.annotation.processing包中。

RuntimeException:

ArithmeticException:表示数学运算异常 ClassNotFoundException:表示类未定义异常 IllegalArgumentException:表示参数格式错误异常 ArrayIndexOutofBoundsException:表示数组下标越界异常 NullPointException:表示空指针异常 NoSuchMethodException:表示方法未定义异常 NumerFormatException:表示将其他数据类型转为数值类型时的不匹配异常。 以上这些类全部存放在java.lang包中。

throw和throws

Java中抛出异常有3种方式:

1.try-catch

2.使用throw是开发者主动抛出异常,即读到throw关键字时代码就一定会抛出异常,

基本语法:throw new Exception(); 是一种基于代码逻辑的判断,并主动抛出异常的方式。

java
public class ThrowTest {
	public static void main(String[] args) {
		String str = "10";
		if(str.equals("10")) {
			throw new NumberFormatException();
		}else {
			int num = Integer.parseInt(str);
		}
	}
}

3.使用throws关键字抛出异常,

try-catch 和 throw都是作用于具体的逻辑代码,throws则是作用于方法,用来描述该方法可能抛出的异常。

java
public class ThrowsTest {
	public static void main(String[] args) throws Exception {
		Cal cal = new Cal();
		cal.cal(0);
	}
}
java
public class Cal {
	public void cal(int num) throws Exception {
		Tools tools = new Tools();
		tools.cal(num);
	}
}
java
public class Tools {
	public void cal(int num) throws Exception{
		int result = 10/num;
	}
}

test()方法使用throws抛出一个第四级别的异常(NumberFormatException),main()方法中调用test()方法时可以try-cath,也可以不添加try-catch:

java
public class ThrowsTest {
	public static void main(String[] args) throws Exception {
    // (1)不使用try-catch,交由虚拟机处理。
		test();
    // (2)使用try-catch,自己捕获处理。
    try {
      test()
    } catch (Exception e) {

    }
	}
	
	public static void test() throws NumberFormatException {
		String str = "10";
		int num = Integer.parseInt(str);
	}
}

但是如果test()throws一个Exception,main()方法中调用时,1)使用try-catch,或者2)也抛出一个异常Exception。

java
public class ThrowsTest {
	public static void main(String[] args) throws Exception {
		test();
	
	public static void test() throws Exception {
		String str = "10";
		int num = Integer.parseInt(str);
	}
}

自定义异常:

创建一个普通的Java类,让它继承Exception或RuntimeException。 直接继承自Exception的类就是checked exception,继承自RuntimeException的类就是runtime exception。

区别:

1)Exception分为checked exception和runtime exception,checked exception表示需要强制去处理的异常,即throw异常之后,需要立即处理该异常,要么try-catch,要么抛给上一层去处理,否则会报错"Unhandled exception type MyException"。

2)runtim exception没有这个要求,throw之后可以不处理。

1.继承自Exception

java
public class Test {
	public static void main(String[] args) {
		try {
			count(-1);
		} catch (MyException e) {
			e.printStackTrace();
		}
	}
	// 继承自Exception,此时要声明一次,“throws MyException”
	public static void count(int num) throws MyException {
		if(num < 0) {
			throw new MyException("学生人数不能小于0");
		}
	}
}
java
public class MyException extends Exception{
	public MyException(String message) {
		super(message);
	}
}
  1. 继承自RuntimeException
java
public class Test {
	public static void main(String[] args) {
		try {
			count(-1);
		} catch (MyException e) {
			e.printStackTrace();
		}
	}
	// 继承自RuntimeException,此时不用声明,直接函数体内直接抛即可。
	public static void count(int num) {
		if(num < 0) {
			throw new MyException("学生人数不能小于0");
		}
	}
}
java
public class MyException extends RuntimeException{
	public MyException(String message) {
		super(message);
	}
}