异常
什么是异常:非正常的,不同于寻常的。并非语法错误。
常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。
比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error;如果你用System.out.println(11/0),那么你是因为你用0做了除数,会抛出 java.lang.ArithmeticException 的异常。
异常发生的原因有很多,通常包含以下几大类:
用户输入了非法数据。
要打开的文件不存在。
网络通信时连接中断,或者JVM内存溢出。
这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。-
要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
非正常情况(出现程序会中断)(查API)
1):Error 表示错误,一般指JVM相关的不可修复的错误,如:系统崩溃,内存溢出,JVM错误等等,由JVM抛出,我们不需要处理。
几乎所有的子类都是以Error作为类名的后缀。
2):Exception 表示异常,指程序中出现不正常的情况,该问题可以修复(处理异常)
几乎所有的子类都是以Exception作为类名的后缀。
---------------------------------------------------------------
出现异常不要紧张,把异常的简单类名,拷贝到API中查看。
-------------------------------------------------------------
捕获异常
如果异常出现的话,会终止程序,所以我们得处理异常:
1):该方法不处理,而是声明抛出,由该方法的调用者来处理。(throws)
2):在方法使用try-catch的语句块来处理异常。
------------------------------------------------------------------------------------------
使用try-catch来处理单个异常。
语法格式:(try-catch不能单独使用)
try{
编写可能出现异常的代码
}catch(异常类型 e){
处理异常代码
//记录日志//打印异常信息//继续抛出异常
如何获取异常信息Throwable类的方法:
参照案例:
1):String getMessage();返回此 throwable 的详细消息字符串。获取异常的描述信息。原因:提示给用户的时候,就提示错误原因。
System.out.println(e.getMessage());// by zero
2):String toString();获取异常类型和异常描述信息。
System.out.println(e.toString());//java.lang.ArithmeticException: / by zero
3):void printStackTrace(); 打印异常的堆栈信息并输出到控制台,不需要使用System.out.print,
包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段都得使用。
重要:现在在catch语句块中必须写e.printStackTrace();目的:查看异常的具体信息,方便调试和修改。
使用try-catch捕获多个异常:
try{
编写可能出现异常的代码
}catch(异常类型 e){
处理异常代码
//记录日志//打印异常信息//继续抛出异常
}catch(异常类型 e){
处理异常代码
//记录日志//打印异常信息//继续抛出异常
}
注意:
1):一个catch语句,只能捕获一个类型的异常,如果需要捕获多个异常,就得使用多个catch语句。
2):代码在一瞬间只能生成一种类型的异常,只需要一个catch捕获,不可能同时出现多个异常。
Finally代码块
Finally语句表示最终都会执行的代码,无论有没有异常。
什么时候的代码必须执行:
当我们在try语句中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开的资源。
------------------------------------------------
Finally的两种用法:
1):try....finally,此时没有catch来捕获异常,因为此时根据应用场景,我们会抛出异常,自己不处理。
2):try...catch...finally;自身需要处理异常,最终还得关闭资源。
注意:finally不能单独使用
--------------------------------------------------
在只有在try或者catch中调用退出JVM的相关方法,否则finally永远都会执行。
System.exit(0);......表示终止JVM虚拟机(详情见system方法)
演示实验finally和不使用finally的区别。必须使用finally才能保证最终执行的代码!
如果finally有return语句,永远返回finally中的结果,避免该情况。
异常Exception分成两大类:
1):编译时期异常:Checked:Exception类的子类,除了运行时期异常其他的就是编译时期异常.
2):运行时期异常:Runtime: RuntimeExeption类和RuntimeException类的子类.
编译时期异常: 要求我们必须处理异常(thows/try-catch),不处理,则编译报错.
运行时期异常: 可处理,可不处理.
推荐使用RuntimeException.
抛出异常
抛出异常
throw :运用于方法内部,用于给调用者返回一个错误。和return一样,结束当前方法。
throws :运用于方法申明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常)。
-----------------------------------------------------------------------------------
throw语句:
运用于方法内部,抛出一个具体的异常对象
throw new 异常类(“异常信息”);终止方法
----------------------------------------------------------------------------------
throw:
一般的,当一个方法出现不正常的情况的时候,我们不知道该方法应该返回什么,此时就返回一个错误,在catch语句块中继续向上抛出异常。
Return 是返回一个值,throw是返回一个错误,返回给该方法的调用者。
查看String charAt源代码:
throws: 运用于方法申明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常)
public static void main(String[] args) {
try {
test("f");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
/*
* 当使用的Exception异常类中的非RuntimeException子类的时候
* 则需要由继承者来处理异常或者自己在方法中处理异常
* 详情可参见异常Exception分类图
*/
public static void test (String a) throws Exception{
if (a.matches("[a-d]")){
System.out.println("请选择答案:");
switch(a){
case "a":System.out.println("答案A"); break;
case "b":System.out.println("答案B"); break;
case "c":System.out.println("答案C"); break;
case "d":System.out.println("答案D");break;
}
}else{
throw new Exception("输入错误...");
或者:
}
}
自定义异常类
为什么需要自定义异常类:
我们说了java中不同的异常类,分别表示着某一种具体的异常情况,那么在开发中总是有些异常情况是SUN没有定义好的,此时我们根据自己的业务的异常情况来定义异常类。
什么是自定义异常类:在开发中根据自己业务的异常情况来定义异常类。
自定义一个业务逻辑异常:logicExeption
异常类如何定义:
方 法 一:自定义了一个受检查的异常类,自定义类,并继承于Exception
方 法 二:自定义了一个运行时期的异常类,自定义类,并继承于RuntimeException