文章目录
1、概述
因为程序出错是不可避免的,所以为了提高程序的健壮性,所有的高级语言都添加了异常的处理方式,被称为异常处理机制。注意开发中的逻辑错误和语法错误不是异常。
java把异常分为两大类:
Error:jvm无法处理和解决的严重问题(类似于重大交通事故) — >不做处理;
Exception:可以处理 —> 处理。
java.lang.Error:
public static void main(String[] args) {
//java.lang.StackOverflowError 栈溢出
test();
//java.lang.OutOfMemoryError 内存溢出
Integer[] arr = new Integer[1024*1024*1024];
}
public static void test() {
test();
}
java.lang.Exception:
偶然出现的编程错误导致的一般问题,可以使用异常处理机制进行处理,目的是让程序能够处
理“错误”,提高程序的健壮性,看起来比较”智能“
处理方式:
1、遇到错误终止程序
2、处理错误,给出提示,继续运行
捕捉错误的时机:
编译时期:编译时期出现错误,需要事先强制处理(checked)。
运行时期:运行时期出现错误(unchecked)。
2、常见异常类型
2.1 编译时期异常:(checked)
(1)IOException
FileNotFoundException
(2)ClassNotFoundException:指定的类不存在
2.2 运行时期异常:(unchecked)
java.lang.RuntimeExcepiton
NullPointExcepiton: 空指针异常
ArrayIndexOutOfBoundsException: 数组下标越界
ClassCastException:类型转换异常
NumberFormatException:数字格式异常
InputMismatchException:输入类型不匹配
ArithmeticException:数学算术异常
//java.lang.NullPointerException
String str = null;
System.out.println(str.length());
//java.lang.ArrayIndexOutOfBoundsException
String[] arr = new String[4];
System.out.println(arr[5]);
//java.lang.ClassCastException
Object obj = new Date();
String str = (String)obj;
//java.lang.NumberFormatException
int num = Integer.parseInt("abc");
//InputMismatchException
Scanner input = new Scanner(System.in);
System.out.println("请输入一个数:");
int res = input.nextInt();
input.close();
//java.lang.ArithmeticException
int res = 10 / 0;
3、处理异常
3.1 处理异常模型:
(1)抓取:进行异常处理
方式一:try-catch-finally;
方式二:throws + 异常类型。
(2)抛出
程序在运行过程中一但出现异常,就会在异常出现的地方生产异常对象,并将此抛出,其后代码不再运行。
3.2 try-catch-finally(自己处理)
格式:
try{
//可能出现异常的代码
}catch(异常类型 变量名称){
//处理异常代码
}catch{
//异常处理代码
}
...
finally{
//一定要执行的代码
}
演示代码:
String str = "abc"; //"abc"
try {
int num = Integer.parseInt(str);// 出现异常
//出现异常 --- 没有机会执行后面代码
Object obj = new Date();
String str2 = (String)obj;
System.out.println(str2);
}catch(NullPointerException e) {
System.out.println("NullPointerExceptio n");
}catch(NumberFormatException e) {
e.printStackTrace(); //异常堆栈信息
//System.out.println(e.getMessage());
//System.out.println("NumberFormatException");
}catch(Exception e) {
e.printStackTrace(); //异常堆栈信息
System.out.println("Exception");
}
System.out.println("执行 ---------------- ");
说明:
- try将可能出现的异常代码包含起来,一但代码出现异常将会在出现异常的地方生成异常对象并抛给系统,之后跳转到catch区域。
- catch则可以根据是否匹配(对应的类型或子类)捕捉到异常对象,再进行异常代码的处理,
处理完异常代码逻辑跳出try-catch块执行剩余的代码,(可能不会执行所有的catch块)。 - 在try-catch声明的变量 不能跳出该结构被找到,所以有时候需要在try-catch块之外声明变量。
- try-catch将编译时出现的异常推迟到运行时异常处理,但仍然可能出错,所以在开发中运行时异常我们一般不做处理。
演示代码(finally):
try {
int num1 = 10;
int num2 = 0;
int res = num1 / num2;
}catch(ArithmeticException e) {
//异常中抛出异常,执行顺序是?
System.out.println("-------e------ ");
Integer.parseInt("abc"); e.printStackTrace();
}finally {
System.out.println("一定会执行 ------- --");
}
//System.out.println("--------");
说明:
- fifinally声明的语句一定会被执行,即使catch中出现异常,或try-catch中有return语句也会被执行。
- 通常jvm不能够及时回收的资源可放入fifinally语句中,比如:数据库连接,输入输出流等资源的
释放。
3.3 throws + 异常模型(模型处理)
写在方法的声明处,说明此方法执行时会抛出异常,一旦程序在执行中出现异常,仍然会在异常代码处生成对象,此对象如果满足声明条件(匹配或子类),则异常就会抛出,异常之后的代码不会被执行。
此方法未处理异常,只是抛给调用者来处理。
public class Test3 {
public static void main(String[] args) {
try {
method2();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void method2() throws IOException {
method();
}
public static void method() throws IOException {
File file = new File("hello.txt");
FileInputStream input = new FileInputStream(file); //读取hello.txt数据
int data = input.read(); //循环读取数据
while(data != -1) { //判断是否有数据
System.out.println((char)data);
data = input.read();
}
input.close();
}
}
3.4 注意事项
- 如果父类中被重写的方法没有throws抛出异常,则子类重写的方法不能抛出,子类只能try-catch处理。
- 子类重写父类方法抛出的异常,不能大于重写的父类方法的异常。
4、手动生成异常throw
class Student {
private int id;
// 方法声明异常
public void regist(int id) throws Exception {
if (id > 0) {
this.id = id;
} else {
// System.out.println("输入的数据有误!");
// 手动抛出异常
throw new Exception("输入的数据有误!");
}
}
@Override
public String toString() {
return "Student [id=" + id +"]";
}
}
public class Test4 {
public static void main(String[]args) {
Student stu = new Student();
try {
stu.regist(-10);
} catch (Exception e) {
System.out.println(e.getMessage());
//e.printStackTrace();
}
}
}
5、用户自定义异常
一般的用户的自定义异常类都是RuntimeException的子类;
自定义异常类通常需要编写几个重载的构造器;
自定义异常需要提供serialVersionUID;
自定义异常通常通过thrwos抛出;
自定义异常最重要的是异常类型的名称,当异常出现时,可以根据名称判断异常类型;
步骤:
创建MyException类继承Exception;
重写父类的方法:构造方法无参及有参(String message)。
/*** 自定义异常类
* @author Administrator
**/
public class MyException extends Exception{
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
}
public class MyExpTest {
public void regist(int num) throws MyException {
if(num < 0) {
throw new MyException("人数为负,不合理");
}else { System.out.println("登记人 数:" + num);
}
}
public void manager() {
try {regist(-10);
} catch (MyException e) {
System.out.println("登记失败, 错误为:" + e.getMessage());
//e.printStackTrace();
}
System.out.println("本次登记结束");
}
public static void main(String[] args) {
MyExpTest test = new MyExpTest();
test.manager(); }
}