1. 异常
-
异常的基本概念:在程序运行过程中出现的错误,称为异常
-
异常的作用:增强程序的健壮性
-
所有异常都是发生在运行阶段的。
-
异常在java中以类的形式存在,每一个异常类都可以创建异常对象。
2. 异常的分类
为何要对异常分类?
假设java中没有对异常进行划分,没有分为:编译时异常和运行时异常,
所有的异常都需要在编写程序阶段对其进行预处理,将是怎样的效果呢?
首先,如果这样的话,程序肯定是绝对的安全的。
但是程序员编写程序太累,代码到处都是处理异常
的代码。
复制代码
2.1 异常的层次结构
2.2 异常的分类
异常主要分为:Error错误、编译时异常(Exception类)、运行时异常(RuntimeException)
-
Error错误:如果应用程序出现了 Error,那么将无法恢复,只能重新启动应用程序,最典型的 Error 的异常是:OutOfMemoryError。
-
编译时异常:出现了这种异常必须处理,不处理 java程序将无法编译通过。
-
运行时异常:此种异常可以不用显示的处理,例如被0 除异常,java没有要求我们一定要处理 。(system.out.println(10 / 0))
3. 对于异常的处理方法
3.1 使用throws 关键字上抛(上报)异常类
- 在声明的位置上继续使用:throws "异常类",将异常抛给方法的调用者(JVM)
- 上抛类似于推卸责任。(继续把异常传递给调用者)
- 一般不建议在main方法使用throws,异常如果发生了,一定会抛给JVM,JVM将终止程序
注意:throws后面可以写多个类,用“,”隔开
public class ExceptionTest05 {
public static void main(String[] args) throws ClassNotFoundException {
doSome();
}
public static void doSome() throws ClassNotFoundException{
System.out.println("doSome!!!!");
}
}
复制代码
3.2 使用try..catch 捕捉异常类
捕捉等于把异常拦下并真正的解决了,调用者是不知道的
try..catch 语法:
try {
调用方法
//以上代码出现异常,直接进入catch语句块中执行
//catch是捕捉异常之后走的分支,进行处理异常操作
} catch (异常类名 变量名) {
异常之后的报错
}
复制代码
try..catch 和 throws 联合使用
public static void main(String[] args){
try {
doSome();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void doSome() throws ClassNotFoundException{
System.out.println("doSome!!!!");
}
复制代码
3.3 两种异常处理方法的注意
-
只要异常没有捕捉,采用上报的方式,此方法的后续代码不会执行
-
try语句块中的某一行出现异常,该行后面的代码不会执行,try...catch捕捉异常之后,后面的代码可以执行
3.3.1 上报和捕捉如何选择
如果希望调用者来处理选择上报,其他情况使用捕捉的方式。
4. 深入try..catch
4.1 catch语句
-
catch()内中的类型可以是具体的异常类型,
-
catch可以写多个。建议catch的时候,精确地一个一个处理。这样有利于程序的调试
-
catch写多个时,从上到下,异常类型必须遵守从小到大:
try { //创建输入流 FileInputStream fis = new FileInputStream("F:\\Java教程\\day08作业.txt"); //读文件 fis.read(); } catch (FileNotFoundException e) { System.out.println("文件不存在!"); } catch (IOException e) { System.out.println("读文件报错了!"); } 复制代码
-
JDK8新特性: catch( )内可使用 “|” 逻辑或 并列多个异常类,表示发生这几个异常类中的某个类时,执行以catch语句中的代码
try { //创建输入流 FileInputStream fis = new FileInputStream("F:\\Java教程\\day08作业.txt"); //进行数学运算 System.out.println(100 / 0); //这个异常是运行时异常,可以处理也可以不处理 } catch (FileNotFoundException | ArithmeticException | NumberFormatException e) { //JDK8新特性,使用逻辑或,表示存在这几个异常类时,执行以下代码 System.out.println("文件不存在?数学异常?空指针不存在?都有可能!"); } 复制代码
4.2 try..catch语句中的finally子句
-
在finally子句中的代码是最后执行的,并且一定会执行,即使try语句出现了异常。
-
finally子句必须和try一起出现,不能单独编写。
-
finally语句通常使用在:
-
通常在finally语句块中完成资源的释放/关闭,因为finally必定会执行 复制代码
示例:
public class ExceptionTest10 {
public static void main(String[] args) {
FileInputStream fis = null;//声明位置放到这,finally才能用到
try {
//创建输入流对象
fis = new FileInputStream("F:\\Java教程\\day08作业.txt");
String s = null;
//空指针异常
s.toString();
System.out.println("hello world");
//流需要关闭,因为流占用资源
//放在这里流可能关不了
//fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}finally {
System.out.println("hello 浩克");
//流放在这里比较保险
if (fis != null) {
try {
//close方法有异常,采用捕捉的方式
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("hello kity");
}
}
复制代码
4.3 try finally 联合使用,try不能单独使用
public class ExceptionTest11 {
public static void main(String[] args)
try {
System.out.println("try....");
return;
} finally {
System.out.println("");
//还是会输出 finally...
}
}
}
复制代码
4.4 只有退出JVM,finally语句才不会执行
public class ExceptionTest12 {
public static void main(String[] args) {
try {
System.exit(0);//退出JVM,finally语句的代码不执行
} finally {
System.out.println("finally...");
}
}
}
复制代码
4.5 finally面试题
public class ExceptionTest13 {
public static void main(String[] args) {
int result = m();
System.out.println(result); //100
}
/*
方法体中的代码必须遵循自上而下的顺序依次逐行执行
return语句一旦执行,整个方法必须结束
*/
public static int m () {
int i = 100;
try {
return i; //return语句是一定最后执行的
} finally {
i++;
}
}
}
/*
反编译之后的效果
public static int m(){
int i = 100;
int j = i;
i++;
return j;
}
*/
复制代码
5. 异常对象有两个重要的方法
-
获取异常简单的描述信息:
String msg = exception.getMessage( ); 复制代码
-
打印异常追踪的堆栈信息(推荐使用):
exception.printStackTrace( ); 复制代码
-
异常追踪信息怎么看?
从上往下逐行看,看自己编写的代码,SUN公司编写的不需要查看 复制代码
方法使用示例:
public class ExceptionTest08 {
public static void main(String[] args) {
NullPointerException e = new NullPointerException("空指针异常");
//获取异常简单描述信息,这个信息是构造方法上面的String参数
String msg = e.getMessage();
System.out.println(msg);
//打印异常堆栈信息
//java后台打印异常信息追踪的时候,采用了异步线程的方式打印的
e.printStackTrace();
System.out.println("hello world");
}
}
复制代码
6. 自定义异常(重点)
-
自定义异常的原因:SUN提供的异常是不够用,需要自定义异常类
-
Java中如何自定义异常类:
第一步,编写一个类继承Exception或者RuntimeException 第二步,提供两个构造方法,无参和有String参数的 复制代码
自定义异常类示例:
7. 关于方法重写不能抛出更多异常
重写之后的方法不能比重写之前抛出更多(更宽泛)的异常,只能更少
class Animal {
public void doSome(){
}
public void doOther() throws Exception {
}
}
class Cat extends Animal{
//编译报错
/*public void doSome() throws Exception {
}*/
//编译正常
/* public void doOther(){
}*/
//编译正常
/*public void doOther() throws Exception {
}*/
//编译正常
/*public void doOther() throws NullPointerException {
}*/
}
复制代码
8. 末尾总结
总结异常中的关键字:
异常捕捉:
try
catch
finally
throws 在方法声明位置上使用,表示上报异常信息给调用者
throw 手动抛出异常!
复制代码
近期评论