赞
踩
在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的,比如:客户输入数据的格式,读取文件是否存在,网络是否始终保持通畅等等。
异常的出现就是为了记录程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止的情况。在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。
异常出现的目的是为了保证程序的健壮性。代码出现问题时,曝出异常,程序员解决这些异常以后再继续向下执行。如果不抛出异常,程序就会在错误的基础上继续执行,这样更加危险。
异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable
,其下有两个子类:java.lang.Error
与java.lang.Exception
,平常所说的异常指java.lang.Exception
。
StackOverFlowError
和OutOfMemoryError
。Throwable中的常用方法:
public void printStackTrace()
:打印异常的详细信息。
包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。
public String getMessage()
:获取发生异常的原因。
提示给用户的时候,就提示错误原因。
public String toString()
:获取异常的类型和异常描述信息(不用)。
我们平常说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。
异常(Exception)的分类:根据在编译时期还是运行时期去检查异常?
先运行下面的程序,程序会产生一个数组索引越界异常ArrayIndexOfBoundsException。我们通过图解来解析下异常产生的过程。
class ArrayTools {
// 对给定的数组通过给定的角标获取元素。
public static int getElement(int[] arr, int index) {
int element = arr[index];
return element;
}
}
public class ExceptionDemo {
public static void main(String[] args) {
int[] arr = { 34, 12, 67 };
int num = ArrayTools.getElement(arr, 4)
System.out.println("num=" + num);
System.out.println("over");
}
}
Java异常处理的五个关键字:try、catch、finally、throw、throws
使用try...catch
语句来捕获程序运行过程中出现的异常。
try{
// 编写可能会出现异常的代码
}catch(异常类型 e){
// 处理异常的代码
// 记录日志/打印异常信息/继续抛出异常等
}
注意:try…catch是一个完整的语句,不能分开使用。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:MM:SS");
try {
Date date = sdf.parse("2021 01 01 12:10:15");
// 如果上面 parse 的代码出问题了,下面这行代码将不会被执行!
System.out.println("解析后的日期是" + date);
} catch (ParseException e) {
System.out.println("解析错误!");
e.printStackTrace();
}
因为异常会引发程序跳转,导致有些语句执行不到。但是如果有一些特定的代码无论异常是否发生,都需要执行,就可以讲这些代码写入到finally代码块里。
什么时候的代码必须最终执行?当我们在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开的资源。
finally的语法:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
注意:finally不能单独使用。
比如在我们之后学习的IO流中,当打开了一个关联文件的资源,最后程序不管结果如何,都需要把这个资源关闭掉。
FileInputStream fis = null;
try {
fis = new FileInputStream("out.txt");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
finally注意事项:如果方法的finally里有return语句,会将前面的return语句覆盖。
在编写程序时,我们必须要考虑程序出现问题的情况。如果程序在运行的过程中出现了问题,我们可以使用throw
关键字将异常抛出。
语法格式:
throw new 异常类名(参数);
示例代码:
private static void divide(int a) {
if (a == 0) {
//System.out.println("除数不能为0");
//return; //可以使用 return 语句结束代码的执行
throw new RuntimeException("除数不能为0");
}
double b = 1.0 / a;
System.out.println("您传入的数字的倒数是" + b);
}
throws
关键字将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,那么必须通过throws进行声明,让调用者去处理。
关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常)。
public class Test {
public static void main(String[] args) {
// divide 方法抛出了异常,不能再这样直接调用
// divide(0);
// 此时,再调用 divide 方法,要么使用try...catch语句处理异常,要么就再把异常向上抛出
try {
divide(3);
}catch(Exception e) {
e.printStackTrace();
}
}
// 在函数声明时就必须要使用 throws 关键字声明异常类型
private static void divide(int a) throws Exception {
if (a == 0) {
// 这里使用 throw 抛出了一个编译时异常
throw new Exception("除数不能为0");
}
double b = 1.0 / a;
System.out.println("您传入的数字的倒数是" + b);
}
}
多个异常时的处理方式。
try {
FileInputStream fis = new FileInputStream("test.txt");
System.out.println(1 / 0);
fis.close();
} catch (FileNotFoundException e) {
System.out.println("文件未找到");
e.printStackTrace();
} catch (IOException e) {
System.out.println("文件关闭失败");
}catch (Exception e) { // 如果有父类,父类的异常处理语句要写在最下面
System.out.println("出问题了");
}
注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。
运行时异常被抛出可以不处理。即不捕获也不声明抛出。
如果finally有return语句,永远返回finally中的结果,避免该情况。
如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出。
Java里的异常类型都继承自Exception类,常见的Java内置异常类型有:
在Java中,我们会使用throw
关键字抛出异常,通常情况下,我们可以创建Java内置的异常类型对象。但是在有些情况下,Java内置的错误类型可能不能够很精确的描述我们的遇到的异常类型,此时就可以考虑自定义异常。
例如:除数为0的时候,Java里默认抛出的异常类型是ArithmeticException
,并不能够很好的描述我们遇到的异常类型,开发中可能会要求抛出一个ZeroDivisionException
自定义异常。
异常分为两大类,编译时异常和运行时异常。我们在开发中,也可以根据我们的业务逻辑,选择继承的异常类型。
Exception
类。RuntimeException
类。Exception
或者RuntimeException
的子类。public class Test {
public static void main(String[] args) throws IOException {
test(0);
}
public static void test(int a) {
if (a == 0) {
// 在这里抛出一个自定义的异常
throw new ZeroDivisionError("除数不能为0");
}
double x = 1.0 / a;
System.out.println("计算的结果是" + x);
}
}
// 根据业务需求分析,ZeroDivisionError 继承自 ArithmeticException 会更加合适
class ZeroDivisionError extends ArithmeticException {
private String s;
ZeroDivisionError(String s) {
super(s);
this.s = s;
}
@Override
public String toString() { // 可以选择重写自定义异常的 toString 方法,在打印异常时输出指定的内容
return "程序运行出错了,错误原因是" + this.s;
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。