异常
-
检查性异常:最具代表的检查异常时用户错误或问题引起的异常,这是程序员无法预见的,例如要打开一个不存在的文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
-
运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
-
错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
Throwable(异常的超类)
-
ERROR(错误)
-
VirtulMachineError(虚拟机异常)
-
StackOverFlowError
-
OutOfMemoryError
-
-
AWTError(GUI编程图形界面化异常)
-
-
Exception(异常)
-
IOException(IO异常)
-
EOFException
-
FileNotFoundException
-
-
RuntimeException(运行时异常)
-
ArrithmeticException(算数异常)
-
MissingResourceException(丢失资源)
-
ClassNotFoundException(找不到类)
-
NullPointerException(空指针异常)
-
IllegalArgumentException
-
ArrayIndexOutOfBoundsException(数组下标越界异常)
-
UnkownTypeException(未知的类型异常)
-
-
Error与Exception区别
Error通常时灾难性的致命错误,时程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
异常处理机制
-
抛出异常
-
捕获异常
-
异常处理五个关键字:
-
try、catch、finally、throw、throws
捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式处理。
捕获异常语法如下:
try:该代码块中编写可能产生异常的代码。
catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。
注意:try和catch都不能单独使用,必须连用。
Finally 块
有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到,而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。
什么时候的代码必须最终执行?
当我们在try语句块中打开了一些物理资源(如 IO流、网络、数据库链接等),都需在使用完之后,最终关闭打开的资源。
finally 的语法: try.....catch...finally:自身需要处理异常,最终还得关闭资源。
1 package com.exception; 2 public class Test { 3 public static void main(String[] args) { 4 int a=1; 5 int b=0; 6 //快捷键 ctrl+alt+t 7 System.out.println(a/b); 8 //要捕获多个异常:从小到大! 9 try {//try监控区域 10 new Test().a(); 11 }catch (ArithmeticException e){//catch(想要捕获的异常类型!) 捕获异常 12 System.out.println("程序出现异常,变量b不能为0" ); 13 }catch (Error e){ 14 System.out.println("Error"); 15 }catch (Exception e){ 16 System.out.println("Exception "); 17 } finally {//处理善后工作 18 System.out.println("finally"); 19 } 20 //finally 可以不要finally 假设IO,资源,关闭! 21 } 22 public void a(){ 23 b(); 24 } 25 public void b(){ 26 a(); 27 } 28 }
抛出异常 throw
在Java中,提供一个throw关键字,它用来抛出一个指定的异常对象。
-
创建一个异常对象。封装一些提示信息(信息可以自己编写)
-
需要将这个异常对象告知调用者。通过关键字throw将这个异常对象传递到调用者处。throw用在方法内,用来抛出一个异常对象,将使用格式: throw new 异常类名(参数---你想告知用户的异常信息);
注意:如果产生了问题,我们通过throw将异常进行抛出,也就是将问题返回给该方法的调用者。那么调用者该怎么处理那?一种是进行捕获处理,另一种就是继续将问题生命出去,使用throws声明处理。
声明异常 throws
将问题标识出来,报告给调用者。如果方法内通过throw抛出了 编译时异常,而没有捕获处理,那么必须通过throws 进行声明,让调用者去处理。关键字 throws 运用于方法声明上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常)。
声明异常语法: 修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2...{}
throws 用于进行异常的声明,若该方法可能有多种异常情况产生,那么在 throws 后面可以写多个异常类,用逗号隔开。最大的异常习惯放后面。
异常处理两种方式
如果异常出现的话,会立刻终止程序,所以我们得处理异常:
-
声明异常:throws该方法不处理,而是声明可能出现的异常,将问题暴露给调用者,让调用者自己处理!
-
捕获异常:try catch 在方法中使用try-catch的语句块直接处理可能出现的异常!
1 package com.exception; 2 public class Test2 { 3 public static void main(String[] args) { 4 try { 5 new Test2().test(1,0); 6 }catch(ArithmeticException e){ 7 e.printStackTrace(); 8 } 9 } 10 //假设这方法中,处理不了这个异常。方法上抛出异常 11 public void test(int a,int b){ 12 if(b==0){//throw throws 13 throw new ArithmeticException();//主动的抛出异常,一般在方法中使用 14 } 15 } 16 }
异常注意事项
多个一擦汗给你使用捕获又该如何处理?
-
多个异常分别处理。
-
多个异常一次捕获,多次处理。
-
多个异常一次捕获一次处理。
一般我们使用一次捕获多次处理的方法,格式如下:
1 try{ 2 //可能出现异常的代码 3 }catch(异常类型A e){//当 try 中出现A类型异常,就用该catch来捕获 4 //处理异常的代码 5 //记录日记/打印异常信息/继续抛出异常 6 }catch(异常类型B e){//当 try 中出现B类型异常,就用该catch来捕获 7 //处理异常的代码 8 //记录日记/打印异常信息/继续抛出异常 9 }
注意:这种处理方式,要求多个catch中的异常不相同,并且若catch中的多个异常之间有子夫类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。
-
运行时异常被抛出可以不处理,即不捕获也不声明抛出。
-
如果finally有return语句,永远返回finally中的结果,避免该情况。
-
如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
-
父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出。(throws)
自定义异常
在开发中根据自己业务的异常情况来定义异常类:
例如 自定义一个业务逻辑异常:PasswordErrorException。密码错误类。
异常类如何自定义:
-
自定义一个检查异常:自定义类 并继承于 java.lang.Exception
-
自定义一个运行时期的异常类:自定义类 并继承于 java.lang.RuntimeException
1 public static void main(String[] args) { 2 UserService ser =new UserService(); 3 try { 4 //异常可以处理,也可以不处理:运行时异常 5 boolean res1=ser.validateName("test1"); 6 System.out.println(res1); 7 } catch (UserNameIsNotExistException e) { 8 e.printStackTrace(); 9 } 10 try { 11 //必须处理异常:有可能是检查异常 12 boolean res=ser.login("teset1","teset"); 13 System.out.println(res); 14 } catch (UserPwdErrorException e) { 15 e.printStackTrace(); 16 } 17 }
1 public class UserService { 2 public boolean validateName(String name) { 3 if(!name.equals("test")) { 4 throw new UserNameIsNotExistException(); 5 }else { 6 return true; 7 } 8 } 9 public boolean login(String name,String pwd) throws UserPwdErrorException{ 10 if(name.equals(pwd)) { 11 return true; 12 }else { 13 throw new UserPwdErrorException(); 14 } 15 } 16 }
1 public class UserNameIsNotExistException extends RuntimeException{ 2 public UserNameIsNotExistException() { 3 super("用户名不存在!"); 4 } 5 }
1 public class UserPwdErrorException extends Exception{ 2 public UserPwdErrorException() { 3 super("用户名或密码错误!"); 4 } 5 }