1、异常的定义
异常:在Java语言中,将程序执行中发生的不正常情况称为“异常”。 (开发过程中的语法错误和逻辑错误不是异常)
2、异常的体系结构
Java程序在执行过程中所发生的异常事件可分为两类:
- Error: Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如: StackOverflowError和OOM。一般不编写针对性的代码进行处理。
- Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:
- 空指针访问
- 试图读取不存在的文件
- 网络连接中断
- 数组角标越界
常见的运行时异常
public class ExceptionTest {
//NullPointerException 空指针异常
@Test
public void test1(){
String s = "abc";
s = null;
System.out.println(s.charAt(0));
}
//ArrayIndexOutOfBoundsException 数组越界异常
@Test
public void test3(){
int[] a = new int[4];
System.out.println(a[5]);
}
//ClassCastException 类型异常
@Test
public void test4(){
Object date = new Date();
String str = (String) date;
System.out.println(str);
}
//ArithmeticException 算数异常
@Test
public void test5(){
int a = 10/0;
System.out.println(a);
}
//NumberFormatException 数值类型异常
@Test
public void test6(){
String str = "abc";
int i = Integer.parseInt(str);
System.out.println(i);
}
//InputMismatchException 输入异常,输出字符串,但是接受只能是int类型
@Test
public void test7(){
Scanner scanner = new Scanner(System.in);
System.out.print("请输入: ");
int i = scanner.nextInt();
System.out.println(i);
}
}
2.1、java中异常类的继承关系
2.2、编译时异常和运行时异常
- 运行时异常:都是
RuntimeException
类及其子类异常,如NullPointerException
(空指针异常)、IndexOutOfBoundsException
(下标越界异常)等,这些异常是***不检查异常***,程序中可以选择捕获处理,也可以不处理。这些异常一般是***由程序逻辑错误引起***的,程序应该从逻辑角度尽可能避免这类异常的发生。
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch
语句捕获它,也没有用throws
子句声明抛出它,也会编译通过。 - 非运行时异常 (编译异常)***:是
RuntimeException
以外的异常,类型上都属于Exception
类及其子类。从程序语法角度讲是必须进行处理的异常,如果***不处理,程序就不能编译通过。如IOException
、SQLException
等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
3、异常的处理
3.1、异常的处理:抛抓模型
抛
: 程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象,并 将此对象抛出,一旦抛出对象以后,其后的代码就不再执行。
抓
: 可以理解为异常的处理方式:
try - catch - finally
throws
3.2、try-catch-finally的try-catch使用
try{
//可能出现异常的代码
}catch(异常类型1 变量名1){
//处理异常的方式1
}catch(异常类型2 变量名2){
//处理异常的方式2
}catch(异常类型3 变量名3){
//处理异常的方式3
}
....
finally{
//一定会执行的代码
}
//说明
1.finally是可选的。(可写,可不写,根据需求来定)
2.使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配。
3.一旦try中的异常对象匹配到某个catch时,就进入catch中进行异常的处理,一旦处理完成,就跳出当前try-catch结构,(在没有写finally的情况下),继续执行其后的代码。
4.建议catch里面的异常类型写Exception,因为Exception是所有异常的父类,包含了所有的异常。
5.catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面,否则报错。
6.常用的异常对象处理方法是:printStackTrace() //输出异常信息
catch(Exception e){
e.printStackTrace()
}
7.在try结构中声明的变量,再出try结构以后,就不能再被调用了,可以在外面声明例如:
int num = 0;
try{
num = .....
}
8.try-catch-finally可以嵌套使用。
// 解决空指针异常的小demo
public class ExceptionTest2 {
public static void main(String[] args) {
String s = "123";
s = null;
try {
System.out.println(s.charAt(0));
}catch (Exception e){
e.printStackTrace();//打印异常信息
}
}
}
3.3、try-catch-finally的finally使用
1.finally是可选的。(可写,可不写,根据需求来定)
2.finally中声明的是一定会被执行的代码。即使catch中又出现异常了,try中有return语句,catch中也有return语句等情况。
3.像数据库连接,输入输出流,网络编程Socket等资源,JVM是不能自动的回收的,我们需要自己手动的进行资源的释放,此时的资源释放,就需要声明在finally中。
3.4、throws方式
异常处理的方式二: throws+异常类型
-
“throws + 异常类型” 写在方法的声明处。
public void methods throws 异常类型{}
。指明此方法执行时,可能会抛出异常类型。一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,就会抛出。异常代码后面的代码,就不再执行!交由方法调用者来解决异常。 -
抛出的异常并没有被真正的处理,要想处理抛出的异常那么就对调用这个异常的方法进行try catch。–(针对于编译时异常,运行时异常可处理可不处理。)
-
demo
-
public class ThrowsTest { public static void main(String[] args) { try { test1(); }catch (Exception e){ e.printStackTrace(); } } public static void test1() throws Exception{//抛出异常交由调用方法者解决 int a = 10/0; System.out.println(a); } }
-
3.5、手动抛出异常
格式:throw new 异常类型("输出的异常信息")
注意: 如果类型不是RuntimeException类下的异常,则需要在方法声明处使用throws抛出异常,或者 在方法体内 try catch 处理该异常,否则编译报错
执行到 throw 语句则后面的语句块不再执行
demo
public class ThrowTest {
public static void main(String[] args) {
int a = -1;
if (a >0){
System.out.println("正确");
}else {
throw new ArithmeticException("错误");
}
}
}
3.6、自定义异常
- 继承于现有的异常结构: RuntimeException 、Exception
- 提供全局常量: serialVersionUID
- 提供重载的构造器,有参和无参。
- demo
public class ExceptionTest3 {
public static void main(String[] args) {
int a = 10;
if (a > 21){
System.out.println("正确的");
}else {
throw new MyException("错误的");
}
}
}
class MyException extends RuntimeException{
static final long serialVersionUID = -7034897190745766939L;
public MyException() {
}
public MyException(String message) {
super(message);
}
}