异常
1、异常介绍
(1)基本概念
Java语言中,将程序执行中发生的不正常情况称为“异常”.(开发过程中的语法错误和逻辑错误不是异常)
快捷键: ctrl+alt+t
,选中try-catch
执行过程中的异常可以分为两大类:
Error
(错误):Java虚拟机无法解决的严重问题。比如:JVM
系统内部错误,资源耗尽等严重情况。比如:StackOverFlowError
和OOM(out of memory),Error
是严重错误,程序会崩溃。Exception
:其他因为编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等。Exception
分为两类:运行时异常和编译时异常
(2)异常体系图
这里画了一些常见经典的异常。
总结:
- 异常分为两大类,运行时异常和编译时异常
- 运行时异常,编译器检查不出来,一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。
java.lang.RuntimeException
类以及它的子类都是运行时异常。 - 对于运行时异常,可以不做处理,因为这类异常很普遍,如果全部处理会对程序的可读性和运行效率产生影响。
- 编译时异常,是编译器要求必须处置的异常,不然编译不能通过,直接报错。
2、运行时异常
常见的运行时异常(RuntimeError)
NullPointerException
空指针异常ArithmeticException
数字运算异常ArrayIndexOutOfBoundsException
数组下标越界异常ClassCastException
类型转换异常NumberFormatException
数字格式不正确异常
3、编译时异常
编译异常实在编译期间,就必须处理的异常,否则代码不能通过编译。
常见的编译异常有:
SQLException
操作数据库,查询表可能发生异常IOException
操作文件时,发生的异常FileNotFoundException
当操作一个不存在的文件时,发生的异常EOFException
操作文件,到文件末尾,发生异常IllegalArguementException
参数异常
4、异常处理
异常处理就是当异常发生事,对异常处理的方式
异常处理的方式:
-
try-catch-finally
程序元在代码中捕获发生的异常,自行处理处理机制:
try{ 代码/可能有异常 }catch(Exception e){ //捕获异常 //1、当异常发生时 //2、系统将异常封装成Exception对象e,传递给catch //3、得到异常对象后,程序员,自己处理 //4、注意,如果没有发生异常,catch代码块不执行 }finally{ //1、不管try代码块是否有异常发生,始终要执行finally //2、所以,通常将释放资源的代码,放在finally }
-
throws
将发生的异常抛出,交给调用者(方法)来处理,最顶级的就是JVM处理机制:
(1)try-catch
方式处理异常注意事项
-
如果异常发生了,则异常发生后面的代码不会执行,直接进入到
catch
块 -
如果异常没有发生,则会顺序执行
try
里面的代码块,不会进入到catch
-
如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用
finally
-
可以有多个
catch
,捕获不能的异常(进行不同的业务处理),要求父类异常在后面,子类异常前面(比如:Exception
在后,NullPointerException
在前,如果发生异常,只会匹配一个catch
举例:
public class TryCatchDetail01 { public static void main(String[] args) { //多个异常,可以多个catch,但是要求子类写在前面,父类写在后面 try { Person person = new Person(); System.out.println(person.getName()); //空指针异常 int n1 = 10; int n2 = 0; int res = n1/n2; //算术异常 } catch (NullPointerException e){ System.out.println("空指针异常"+e.getMessage()); }catch (ArithmeticException e){ System.out.println("算术异常"+e.getMessage()); } catch (Exception e) { System.out.println(e.getMessage()); } finally { } } } class Person{ private String name; public Person() { } public String getName() { return name; } }
-
可以进行
try-finally
配合使用,这种相当于没有捕获异常,程序会直接崩溃。应用场景,执行一段代码,不管是否发生异常,都会执行某个业务逻辑。try{ //可能发生的语句 }finally{ //必须执行的 }
5、throws处理异常
(1)基本介绍
- 如果一个方法(中的执行语句时)可能呢生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示的声明抛出异常,表明该方法不对这些异常进行处理,而是由该方法的调用者进行处理。
- 在方法声明中用throws语句可以什么抛出异常的列表,throw后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。
举例:
// public void f2() throws FileNotFoundException{
// public void f2() throws FileNotFoundException, NullPointerException, ArithmeticException{
public void f2() throws Exception{
//抛出异常,让调用f2的调用者进行处理
//throws后面可以是当前异常的父类,也可以抛出多个异常
FileInputStream fis = new FileInputStream("d://aa.txt");
}
}
(2)注意事项和使用细节
- 对于编译异常,必须进行处理
- 对于运行异常,程序没有运行,默认是
throws
处理 - 子类重写父类的方法是,对于抛出异常的规定:子类重写的方法,所抛出的异常要么和父类抛出的异常一致,要么是父类抛出异常的子类。
- 在
throws
的过程中,如果有方法try-catch
,就相当于处理异常,可以不用throws
举例:
public class ThrowsDetails {
public static void main(String[] args) {
}
public static void f1(){
//运行时异常,会默认throws
f2();
}
public static void f2() throws NullPointerException{
}
public static void f3() throws Exception{
//而编译类型的异常必须进行处理,否则会报错,调用者抛出的异常可以是之前的异常,或者之前的异常的父类
f4();
}
public static void f4() throws FileNotFoundException {
}
}
class A{
public void f1() throws Exception{
}
}
class B extends A{
@Override
//子类抛出的异常必须是父类的子类或者父类的异常
public void f1() throws NullPointerException {
}
}
6、自定义异常
(1)基本概念
当程序中出现了某些错误,但是该错误信息并没有在Throwable
的子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息。
(2)基本步骤
- 定义类,自定义异常类名,继承
Exception或者RuntimeException
- 如果继承的是
Exception
,属于编译异常 - 如果继承的是
RuntimeException
,属于运行异常,一般来说都是继承RuntimeException
举例:
//自定义一个异常
//一般情况下,都是自定义为运行时异常,RuntimeException,这样可以使用默认的处理机制
class AgeException extends RuntimeException{
public AgeException(String message) {//构造器
super(message);
}
}
(3) throws对比throw
举例:
public class CustomException {
//throws
public static void main(String[] args) throws Exception{
int age = 180;
if(!(age >= 18 && age <= 120)){
//这里可以根据构造器,设置信息
//throw
throw new AgeException("年龄需要在18和120之间");
}
System.out.println("年龄范围正确");
}
}