异常概述
什么是异常(Exception:Java在运行过程当中出现的错误
Throwable
类是 Java 语言中所有错误或异常的超类。
异常:分为运行时异常和编译时异常,我们需要了解的是运行时异常
JVM异常处理方式
JVM是怎么处理异常的
main收到这个异常时,会做两种处理方式
1.自己来去处理
2.自己处理不了,交给调用者jvm来处理
JVM内部会有一个异常处理机制,会把异常的名称,异常信息输出到控制台(创建一个异常对象)
new ArithmeticException("/by zero");
try_catch处理异常
自己处理异常
1.try...catch...finally
基本格式:
try {
可能出现异常的代码
}catch(异常类型){
}finally {
处理完异常最后做的处理
}
Try:用来检测异常
Catch:用来捕获异常
Finally:释放资源
try {
int a = 10 / 0;
System.out.println(a);
} catch (ArithmeticException a) {
System.out.println(a);//java.lang.ArithmeticException: / by zero
System.out.println("除数不能为0");
}
10/0;会创建一个异常对象
new ArithmeticException("/by zero");赋值给a,int a 接收不了,
此时就把异常对象传给catch当中的参数a,能够接收,就会执行了catch当中的内容,程序也没有终止
只有在try出现问题的时候才会执行catch当中的内容
出现问题的时候catch处理完毕之后,后续的代码继续执行
处理多个异常
try...catch处理多个异常
在try当中可能会出现不同的异常类型,此时可以使用多个catch来进行处理
try {
int[] arr = { 10, 20, 30 };
System.out.println(arr[4]);// ArrayIndexOutOfBoundsException
int a = 10 / 0;// ArithmeticException
// 在try当中出现了异常,会立马停止执行了try当中后续的代码
// 出现异常时会立马跳到catch
System.out.println("aaa");
System.out.println("aaa");
} catch (ArithmeticException a) {
System.out.println("算数异常");
} catch (ArrayIndexOutOfBoundsException arr) {
System.out.println("数组越界异常");
}catch(Exception e) {
System.out.println("其他异常");
}
Exception e不能写在最上面,写在上面会报错,因为下面的永远不会执行到,最常用的
不知道报什么异常的时候,可以写成
try {
int[] arr = { 10, 20, 30 };
System.out.println(arr[4]);// ArrayIndexOutOfBoundsException
int a = 10 / 0;// ArithmeticException
} catch(Exception e) {
System.out.println("其他异常");
}
JDK7之后处理多个异常
try {
int[] arr = { 10, 20, 30 };
System.out.println(arr[4]);// ArrayIndexOutOfBoundsException
int a = 10 / 0;// ArithmeticException
System.out.println("aaa");
System.out.println("aaa");
//从jdk7之后可以这样写
} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println("除数不能为0或者数组越界");
}
运行时异常与编译时异常
什么是运行时异常?
所有的RuntimeException类及其子类成为运行时异常,在编译时不会报错,在运行过程程序终止运行
什么是编译时异常?
程序员必须显示处理,否则程序就会发生错误无法通过编译
编译时异常发生的情况
FileInputStream fl = new FileInputStream("abc.txt");
运行时异常与编译时异常的区别
运行时异常,程序员犯的错误,需要回来修改代码
编译时异常在编译某个程序的时候,有可能会这样那样的错误,
比如文件找不到,这样的异常就必须在编译时处理
如果不处理就编译不通过
try {
FileInputStream fl = new FileInputStream("abc.txt");
}catch(Exception e) {
System.out.println("发生异常了");
}
获取异常信息
常用方法:
1.获取异常信息
,返回字符串,参数
try {
int a = 10/0;
}catch(Exception e) {
System.out.println(e.getMessage());// / by zero
}
2.获取异常类名
和异常信息
try {
int a = 10 / 0;
} catch (Exception e) {//Exception e = new ArithmeticException("/ by zero")
System.out.println(e.toString());//java.lang.ArithmeticException: / by zero
System.out.println(e);//java.lang.ArithmeticException: / by zero
}
3.获取异常类名和异常信息,及异常出现的位置(看异常信息从下往上来去查看)
try {
int a = 10 / 0;
} catch (Exception e) {
e.printStackTrace();
}
throw抛出异常
1.抛出运行时异常,不需要处理
class Person {
private int age;
public void setAge(int age) {
if (age > 0 && age <= 150) {
this.age = age;
} else {
// 1.System.out.println("年龄不正确");
// 2.出现异常,终止程序运行
throw new RuntimeException("年龄不正确");
}
}
}
2.抛出编译时异常
class Person1 {
private int age;
public void setAge(int age) throws Exception {//抛出异常
if (age > 0 && age <= 150) {
this.age = age;
} else {
// 3.编译时异常
throw new Exception("年龄不正确");
}
}
}
抛出了一个编译时异常,必须要得要有人处理
如果不处理,必须继续往上抛,抛给方法调用者
Person1 per = new Person1();
per.setAge(-10);
此时由于setAge内部抛出了一个异常,在调用该方法时必须得要处理
1.必须要处理异常
Person1 per = new Person1();
try {
per.setAge(-10);
} catch (Exception e) {
e.printStackTrace();
}
2.继续往上抛出
自己不处理,抛给main方法调用者jvm处理,同样是控制台报出错误
public static void main(String[] args) throws Exception {
Person1 per = new Person1();
per.setAge(-10);
}
throw与throws的区别
throw:
用在方法内,跟的是异常对象名称
只能抛出一个异常对象
表示抛出异常
throws:
用在方法生命后面,跟的是异常类名
可以跟多个异常类名,中间使用逗号隔开
表示抛出异常,由方法调用者来处理
finally
fianlly特点
:
被finally控制的语句一定会被执行到
//只要执行了try,就会执行finally
try {
System.out.println(10 / 0);
} catch (Exception e) {
System.out.println("错误:除数不能为0");
} finally {
System.out.println("执行了finally");
}
特殊情况
:在执行finally之前jvm退出了
try {
System.out.println(10 / 0);
} catch (Exception e) {
System.out.println("错误:除数不能为0");
//System.exit(0);
return;//终止当前方法运行,是不能阻止finally
} finally {
System.out.println("执行了finally");//exit,jvm停止了,不会执行
}
System.out.println("end");//不会被执行,方法已经终止了
finally作用
:
用来释放资源,在IO操作中经常见到
退出程序
:
retrun,终止当前方法运行,并不能阻止finally
exit(0),jvm停止了,finally就不会执行
finally返回值问题
int x = 10;
try {
x = 20;
System.out.println(1 / 0);
return x;
} catch (Exception e) {
x = 30;
return x;//return返回的是当时的值
} finally {//finally一般不做return,只作资源的释放
x = 40;
}
}
System.out.println(Demo8.test());//30
自定义异常
为什么自定义异常:
系统自带的异常类名称有很多,通过类型就能看出是什么异常,算术异常,空指针异常,数组越界异常
自己也想抛出一个异常,类名是自己定义的,通过类名就能知道是什么类型的异常
自定义运行时的异常
:
1.定义一个类继承RuntimeException
2.抛出异常时,抛出自己定义的异常类名
class AgeBoundsException extends RuntimeException{
}
throw new AgeBoundsException();
自定义编译时异常
:
1.定义一个类继承Exception
class AgeBoundsException extends Exception{
}
2.抛出异常时,抛出自己定义的异常类名
public static void main(String[] args) throws AgeBoundsException {
throw new AgeBoundsException();
}
以上两种报异常的方法都是不带参数的
找方法的eclipse的快捷键:Ctrl+O
自定义带参数的异常
1.定义一个类继承RuntimeException或者Exception
在类当中提供一个有参数的构造方法
把参数传给父类构造器
class AgeBoundsException extends Exception{
AgeBoundsException(String message){
super(message);
}
}
2.抛出异常时,抛出自己定义的异常类名并且传入对应的参数
public static void main(String[] args) throws AgeBoundsException {
throw new AgeBoundsException("年龄出问题了");
}