java异常捕获机制
- try块:包含着可能出现错误的代码片段
- catch块:列举try中出现的错误种类,并有针对性的处理。
catch块可以出现1-n次。
好的编程习惯,在最后一个catch中捕获Exception异常。 - 注意:
catch的捕获是由上至下的,所以不要把父类异常写在子类异常的上面,否则子类异常永远没有机会处理!
throw关键字:用于主动抛出异常
使用环境:
我们常在方法中主动抛出异常。但不是什么情况下我们都应该抛出异常。原则上,自身决定不了的应该抛出。
方法中什么时候该自己处理异常什么时候该抛出?
方法通常有参数,调用者在调用我们的方法帮助解决问题是通常会传入参数,若我们方法的逻辑是因为参数的错误而引发的异常应该抛出,若是我们自身的原因应该自己处理。
throws关键字
声明方法的时候,我们可以同时声明可能抛出的异常种类,通知调用者强制捕获。
就是所谓的“丑话说前面”。
注意区分throw和throws关键字。笔试常问。
throw是抛出异常时使用的,throws是用于方法声明时定义可能抛出的异常。
java中抛出异常运行机制:
java虚拟机在运行程序时,一旦在某行代码运行时出现错误,jvm会创建这个错误的实例,并抛出。这时jvm会检查出错代码所在的方法是否有try捕获,若有,则检查catch块是否有可以处理该异常的能力。若没有,则将该异常抛给该方法的调用者。以此类推,直到抛至main方法外仍没有解决。那么jvm会终止该程序。
- throws可以在方法声明时声明抛出的异常。
原则上throws声明的异常,一定在该方法中会出现,否则没有意义。相反的,若方法中我们主动通过throw抛出一个异常,应该在throws中声明该种类异常,通知外界捕获。 - java中的异常Exception分为:
运行时异常:编译时不检查异常
可检查异常:编译时检查
RuntimeExcption:运行时异常。若方法中抛出该类异常或其子类,那么声明方法时可以不在throws中列举该类抛出的异常。
除此之外其他可检查类型必须在声明方法时在throws中列举该种类异常。 - 重写方法时的异常处理
如果使用继承时,在父类别的某个方法上宣告了throws某些异常,而在子类别重新定义该方法时,您可以:
1、不处理异常(重新定义时不设定throws)
2、可仅throws父类别中被重新定义的方法之某些异常
3、可throws被重新定义的方法上之子类别
但是您不可以:
1、throws出额外的异常
2、throws被重新定义的方法上之异常之父类别
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* java异常处理机制
* 我们程序中可以捕获的是Exception的子类异常
* 而java中的异常有两大类
* Exception:程序级别的异常,我们可控
* Error:系统级别的异常,我们不可控
*
* 所以我们关心的是Exception的相关子类!
*
* 异常处理语句
* try{
* 可能发生异常的代码片段
* }catch(Exception e){//列举代码中可能出现的异常类型
* 当出现了列举的异常类型后,在这里处理
* }
*/
public class ExceptionTest {
public static void main(String[] args) {
try {
String info = "hello";
//这里会引发空指针异常!
System.out.println(info.length());
System.out.println(info.charAt(9));
}catch (NullPointerException e){
System.out.println("这里字符串是空的!");//这里字符串是空的
}catch (StringIndexOutOfBoundsException e){
System.out.println("字符串没有那么长!");//字符串没有那么长!
}catch (Exception e){
/*良好的习惯,在异常捕获机制的最后书写catch(Exception e)
* 捕获未知的错误(或不需要针对处理的错误)。*/
}
try {
//String result = getGirlFirend("女神");
//System.out.println("我追到了女神么?"+result);
getGirlFirend(null);
}catch (Exception e){
//我们应该在这里捕获异常并处理。
System.out.println("没追到。。。");
}
try {
StringToDate("2018-03-09");
//catch中必须包含有效的捕获stringToDate方法throws的异常
} catch (ParseException e) {
//输出这次错误的栈信息,可以直观的查看方法调用过程和出错的根源。
e.printStackTrace();
}
/**
* try-catch中finally块
*
* finally块定义在catch块的最后。只能出现一次。(0-1次)
*
* 无论程序是否出错都会执行的块!
* 无条件执行,前面有return都还会执行!
*
* 注意final和finally的区别。
*/
try {
String info = null;
System.out.println(info.charAt(9));
}catch(NullPointerException e){
e.printStackTrace();
}catch (StringIndexOutOfBoundsException e){
e.printStackTrace();
}finally {
//里面的语句无条件执行
System.out.println("finally!!!");
}
System.out.println("程序结束了!");//程序结束了!
}
/**
* throw关键字,可以主动抛出一个异常
*
* 应用环境:当我我们的方法出现错误时,这个错误我们不应该去解决,而是
* 通知调用方法方去解决,会将这个错误告知外界,而告知外界
* 的方式就是throw异常(抛出异常)
*/
/**
* 介绍女朋友
* @param name 女朋友名字
* @return 是否同意
*/
public static String getGirlFirend(String name) {
try {
if ("春哥".equals(name)) {
return "行";
} else if ("曾哥".equals(name)) {
return "行";
} else if ("我女朋友".equals(name)) {
return "不行";
} else {
/*当出现了错误(可能是业务逻辑上的,不一定是真实异常)
* 我们可以主动向外界抛出一个异常!*/
throw new RuntimeException("人家不干!");
}
}catch(NullPointerException e){
throw e;//出错了不解决,抛给调用者解决。
}
}
/**
* throws关键字
* 声明抛出异常的种类
* 作用是通知调用者必须捕获异常
*/
public static Date StringToDate(String str) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
/**
* SimpleDateFormat的parse方法在声明的时候就使用了throws
* 强制我们调用parse方法时必须捕获ParseException
* 我们的做法是添加try-catch捕获该异常,或者在我们的方法
* 声明也追加这种异常的抛出。
*/
Date date = format.parse(str);
return date;
}
/**
* 抛出异常规范
* throws的位置
* 方法声明时参数列表的后面,方法体前半个大括号前面
*/
public static void ruleTest(String str) throws ParseException {
if (str==null){
/**
* 我们在方法中主动抛出异常,应该在方法声明时声明该异常的抛出
*/
/**
* NullPointerException是非检查异常(RuntimeExcption的子类)
* 所有我们抛出该类异常实例时,方法声明处无需添加throws来
* 列举该类异常的抛出。编译器在编译类时也忽略对这类异常
* 抛出的检查(编译时不看他是不是在throws中被列举)。
*/
throw new NullPointerException("有错误");
}
/*抛出非RuntimeExecption异常,该类异常称为检查异常
* 编译器在编译该类时若发现方法中抛出了此类异常,
* 那么一定会检查方法声明时是否含有throws该类异常的声明或对该异常进行try-catch异常捕获处理,
* 若没有就判断为语法错误,编译不通过!
*/
throw new ParseException("",0);
}
}









网友评论