java异常捕获机制
try块:包含着可能出现错误的代码片段
catch块:列举try中出现的错误种类,并有针对性的处理。catch块可以出现1-n次。好的编程习惯,在最后一个catch捕获Exception异常。
注意:
catch的捕获是由上至下的,所以不要把父类异常写在子类异常的上面,否则子类异常永远没有机会处理!
java中抛出异常:
java虚拟机(jvm)在运行程序时,一旦在某行代码运行时出现了错误,jvm会创建这个错误的实例,并抛出。这时jvm会检查出错代码所在的方法是否有try捕获,若有,则检查catch块是否有可以处理该异常的能力。若没有,则将该异常抛给该方法的调用者。以此类推,直到抛至main方法外仍没有解决。那么jvm会终止该程序。
package day01;
/**
* java异常处理机制
* 我们在程序中可以捕获的是Exception的子类异常
* 而java中的异常有两大类。
* Exception:程序级别的异常,我们可控
* Error:系统级别的异常,我们不可控。
* 所以我们关心的是Exception的相关子类!
*
* 异常处理语句
* try{
* 可能发生异常的代码片段
* }catch(Exception e){
* //列举代码中可能出现的异常类型,当出现了列举的异常类型后,在这里处理
* }
* try{
* }catch(Exception e){
* }
* @author Administrator
*
*/
public class DemoException {
public static void main(String[] args) {
try{
// String info = null;
String info1 = "hello";
//这里会引发空指针异常!
// System.out.println("这个字符串长度:"+info.length());
System.out.println("第10个字符是:"+info1.charAt(9));
}catch(NullPointerException e){
System.out.println("这里的字符串是空的!");
}catch(StringIndexOutOfBoundsException e){
System.out.println("字符串没有那么长!");
}catch(Exception e){
/**
* 良好的习惯,在异常捕获机制的最后书写catch(Exception e)
* 捕获未知的错误(或不需要针对处理的错误)。
*/
}
System.out.println("程序结束了!");
}
}
throw关键字:用于主动抛出异常
使用环境:
我们常在方法中主动抛出异常。但不是什么情况下我们都应该抛出异常。原则上,自身决定不了的应该抛出。
方法中什么时候该自己处理异常什么时候该抛出?
方法通常有参数,调用者在调用我们的方法帮助解决问题时通常会传入参数,若我们方法的逻辑是因为参数的错误而引发的异常应该抛出,若是我们自身的原因应该自己处理。
package day01;
/**
* throw关键字,可以主动抛出一个异常
*
* 应用环境: 当我们的方法出现错误时,这个错误我们不应该去解决,而是
* 通知调用方法方去解决时,会将这个错误告知外界,而告知外界的方式就是throw异常(抛出异常)
*
* @author Administrator
*
*/
public class DemoThrow {
public static void main(String[] args) {
try{
/**
* 通常我们调用方法时需要传入参数的话,那么这些方法都不会自动处理异常
* 而是将错误抛给我们解决。
*/
String result = getGirlFirend("女神");
System.out.println("我追到了女神吗?"+result);
}catch(Exception e){
//我们应该在这里捕获异常并处理。
System.out.println("没追到。。。");
}
}
/**
* 介绍女朋友 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关键字:
声明方法的时候,我们可以同时声明可能抛出的异常种类,通知调用者强制捕获。
就是所谓的丑话说前面。
注意区分throw和throws关键字。笔试常问。
throws可以在方法声明时声明抛出的异常。原则上throws声明的异常,一定要在该方法中抛出。否则没有意义。相反的。
若方法中我们主动通过throw抛出一个异常,应该在throws中声明该种类异常,通知外界捕获。
package day01;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* throws关键字
* 声明抛出异常的种类
*
* 作用是通知调用者必须捕获的异常
* @author Administrator
*
*/
public class DemoThrows {
public static void main(String[] args) {
try{
Date today = stringToDate("2013-05-20");
//catch中必须含有有效的捕获stringToDate方法throws的异常
}catch(ParseException e){
/**
* 输出这次错误的栈信息
* 可以直观的查看方法调用过程和出错的根源。
*/
e.printStackTrace();
}
}
/**
* 将一个字符串转换为一个Date对象 java.util.Date
* 抛出的异常是字符串格式错误
* @param str
* @return
*/
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;
}
}
java中的异常Exception分为:
运行时异常:编译时不检查异常
可检查异常:编译时检查
RuntimeException:运行时异常。
若方法中抛出该类异常或其子类,那么声明方法时可以不在throws中列举该类抛出的异常。
package day01;
import java.text.ParseException;
import java.util.Date;
/**
* 抛出异常的规范
* @author Administrator
*
*/
public class DemoCheckException {
public static void main(String[] args) {
try{
Date date = stringToDate("1988-02-25");
}catch(ParseException e){
e.printStackTrace();
}
}
/**
* throws的位置:
* 方法声明时参数列表的后面,方法体前半个大括号前面
* @param str
* @return
* @throws ParseException
*/
public static Date stringToDate(String str) throws ParseException{
if(str == null){
/**
* 我们在方法中主动抛出异常,应该在方法声明时声明该异常的抛出
*
* NullPointerException是非检查异常(RuntimeException子类)
* 所以我们抛出该类异常实例时,方法声明处无需添加throws来列举该类异常的抛出。
* 编译器在编译该类时也忽略对这类异常抛出的检查(编译时不看他是不是在throws中被列举)。
*/
// throw new NullPointerException("有错误");
/**
* 抛出非RuntimeException异常,这类异常称为检查异常
* 编译器在编译该类时若发现方法中抛出了此类异常。那么一定会检查方法声明
* 处是否含有throws这类异常的声明,若没有就判定为语法错误。编译不通过!
*/
throw new ParseException("有错误",0);
}
return null;
}
}
package day01;
/**
* try-catch中的finally块
*
* finally块定义在catch块的最后。只能出现一次。(0-1次)
*
* 无论程序是否出错都会执行的块!
* 无条件执行!
* 注意final和finally的区别。
* @author Administrator
*
*/
public class DemoFinally {
public static void main(String[] args) {
try{
String info = "23223232332";//null
System.out.println("字符串第10个字符"+info.charAt(9));
}catch(NullPointerException e){
e.printStackTrace();
}catch(StringIndexOutOfBoundsException e){
e.printStackTrace();
}finally{
//里面的语句无条件执行!
System.out.println("finally!!!");
}
System.out.println("程序结束了");
}
}
package day01;
/**
* finally面试题
* @author Administrator
*
*/
public class FinallyDemo {
public static void main(String[] args) {
System.out.println(test(null)+","+test("0")+","+test(""));
/*
* 输出结果?
* 4,4,4
* finally无条件执行
*/
}
public static int test(String str){
try{
return str.charAt(0)-'0';
}catch (NullPointerException e){
return 1;
}catch (RuntimeException e){
return 2;
}catch (Exception e){
return 3;
}finally{
return 4;//它return前面的return都无效了
}
}
}