Java异常处理

Throwable

所有异常类的超类

Error

严重的异常,比如加载大量图片的时候内存会溢出,就属于严重异常,可以使用第三方框架ImageLoader去加载图片。

Exception

分为编译时期异常和运行时期异常;

编译时期异常:只要出现的不是运行时期异常,统称为编译时期异常。

        如:ParseException,String转换Date时解析错误。

编译时期异常必须进行处理否则无法通过编译。

运行时期异常:RuntimeException,可以通过编译但是代码不严谨。

        如:NullPointerExceptino空指针异常

处理异常

    throws

直接将异常抛出。对于编译时期的异常如果不做异常处理编译就无法通过,执行该异常处理后,当发生异常时会将异常类显示在控制台上。

    throws表示可能会发生异常,有些方法中自带了异常就必须抛出才能编译通过

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Except {
public static void main(String[] args) throws ParseException {
	//抛出ParseException异常,但不代表该异常一定会发生
	SimpleDateFormat adf=new SimpleDateFormat("yy-MM-dd");
	Date d=new Date();
	d=adf.parse("2018:12:30");//输入了不正确的格式
	System.out.println(d);
}
}
/**
Exception in thread "main" java.text.ParseException: Unparseable date: "2018:12:30"
at java.base/java.text.DateFormat.parse(Unknown Source)
at ExceptDemo.Except.main(Except.java:12)
*/

注意事项:

    子类继承父类的时候的注意事项

  • 子类重写父类的方法的时候,子类的方法的抛出的异常必须和父类的方法异常一样,要么是父类方法异常的子类
  • 子类重写父类方法的时候,如果父类中的这个方法没有抛出异常,那么子类重写的这个方法也不能抛出异常,只能try...catch

throw

表示抛出一个异常对象,用匿名内部类的方式

throws和throw的区别
 throwsthrow
功能抛出异常,它后面跟的异常类名,并且可以多个异常类名中间逗号开抛出的一个异常对象
位置在方法上抛出,由调用者处理在语句体中抛出的,由语句体进行处理
确定性表示的是出现异常的可能性表示抛出异常的肯定性

public class Except {
	public static void main(String[] args) {
		int a = 10;
		int b = 0;
		if(b==0) {
			throw new ArithmeticException();//匿名内部类的方式跟一个异常对象
		}else {
			System.out.println(a / b);// 除数为0
		}
		System.out.println("程序结束");
	}
}

/**
Exception in thread "main" java.lang.ArithmeticException
	at ExceptDemo.Except.main(Except.java:8)
 */

    try...catch...finally

异常捕获机制,try中的代码如果发生异常就会显示catch中的异常提醒。

finally为对异常的处理,finally中的代码一定会执行。用于解决异常,比如数据库的回滚操作。

final,finally,finalize的区别
final修饰类,该类不能被继承;修饰变量,该变量是常量;修饰成员方法,该方法无法重写
finalize运行垃圾回收器gc(),实际是调用finalize()方法,和垃圾回收器有关系
finally在io,数据库中以及后面对数据库操作(DBUtuls/c3p0/Hibernate/MyBatis)里面中释放资源的

解决一个异常

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Except {
	public static void main(String[] args){
		SimpleDateFormat adf = new SimpleDateFormat("yyyy-MM-dd");
		Date d = new Date();
		try {
			d = adf.parse("2008:5:20");// 输入了不正确的格式
		} catch (ParseException e) {
			e.printStackTrace();//直接通过异常类对象将异常显示在控制台
		}
		System.out.println(d);
	}
}
/**
java.text.ParseException: Unparseable date: "2008:12:30"
	at java.base/java.text.DateFormat.parse(Unknown Source)
	at ExceptDemo.Except.main(Except.java:12)
Fri May 18 22:14:19 CST 2018
 */

可以看出来try...catch异常处理方式并不会直接终止程序,而是在发生异常的位置在控制台显示异常。程序跳过了异常部分直接打印了当前的时间。

注意

  • 编译器中可以通过shift+alt+z快速给选中的代码添加try...catch异常处理
  • try中的代码应当越少越好。
  • catch中可以直接抛出异常也可以确切的说明异常。

解决多个异常

    对于一段代码中有多个异常可以使用一个try多个catch的方式处理,应当将范围大的异常放在下面。

public class Except {
	public static void main(String[] args) {
		int a = 10;
		int b = 0;
		int[] arr = { 1, 2, 3 };
		try {
			System.out.println(a / b);// 除数为0
			System.out.println(arr[3]);// 脚标越界
		} catch (ArrayIndexOutOfBoundsException e) {
			System.err.println("数组脚标越界");
		} catch (ArithmeticException e) {
			System.err.println("除数不能为0");
		} catch (Exception e) {//最大的异常放在最下面
			System.err.println("程序出现问题");
		}
		System.out.println("程序结束");
	}
}

/**
除数不能为0
程序结束
 */

这种处理方式当try中的代码出现问题只会抛出遇到的第一个异常,然后跳过try中的代码继续执行程序。

JDK 7以后新增的方式

可以在一个catch中通过    |    分隔添加多个异常,注意添加的异常是同一级别的。

public class Except {
	public static void main(String[] args) {
		int a = 10;
		int b = 0;
		int[] arr = { 1, 2, 3 };
		try {
			System.out.println(a / b);// 除数为0
			System.out.println(arr[3]);// 脚标越界
		} catch (ArrayIndexOutOfBoundsException | ArithmeticException e) {
			System.out.println("程序出现问题了");
		} finally {
			// finally中的代码一定会执行,除非在这之前JVM退出了
			System.out.println("这里通常用于释放资源");
		}
		System.out.println("程序结束");
	}
}

/**
程序出现问题了
这里通常用于释放资源
程序结束
 */

如果在方法中catch中存在return的问题

public class Except {
	public static void main(String[] args) {
		System.out.println(get());
	}
	public static int get() {
		int a = 10;
		int b = 0;
		try {
			System.out.println(a/b);
		} catch (Exception e) {
			a=30;
			System.out.println("catch");
			return a;
		}finally {
			a=40;
			System.out.println("finally");
		}
		return a; 

	}
}

/**
catch
finally
30
 */

虽然finally中的方法一定会执行,从例题中看出输出了finally说明finally中的代码执行了,但是finally是在catch之后执行的,在catch中已经记录了返回值为30,程序在记录了返回值为30后再执行了finally中的方法。所以最终的结果是30。

自己定义异常类

import java.util.Scanner;

class MyException extends Exception {
	// 定义一个自定义异常类,继承自Exception
	public MyException() {
		super();
	}

	// 使用构造方法定义异常
	public MyException(String message) {
		super(message);
	}

}

class Teacher {
	// 校验学生成绩的功能
	public void check(int score) throws MyException {
		// 方法上要抛出异常
		if (score < 0 || score > 100) {
			// 抛出异常类的对象
			throw new MyException("该学生成绩不符合...");
		} else {
			System.out.println("该学生成绩没有问题");
		}

	}
}

public class Except {
	public static void main(String[] args) throws MyException {
		// 创建键盘录入对象
		Scanner sc = new Scanner(System.in);
		// 接收数据
		System.out.println("请输入学生成绩:");
		int score = sc.nextInt();
		Teacher t = new Teacher();
		t.check(score);// 执行带异常处理的方法
	}

}

/**
请输入学生成绩:
200
Exception in thread "main" ExceptDemo.MyException: 该学生成绩不符合...
	at ExceptDemo.Teacher.check(Except.java:24)
	at ExceptDemo.Except.main(Except.java:40)
 */

阅读更多
个人分类: Java
想对作者说点什么? 我来说一句
相关热词

没有更多推荐了,返回首页

关闭
关闭
关闭