/*
什么是异常(Exception)异常是程序在编译或运行过程中出现的例外,这些例外有的可以避免,有的却无法避免。Exception类继承自Throwable类,Throwable类还有一个子类ErrorError代表的是错误,不再是程序员编程处理的范围。检查异常也称为编译期异常不可避免,必须进行异常处理,要不编译器报错Exception以及它的子类(除去RuntimeException)未检查异常也称为运行时异常可以避免,不需要必须处理RuntimeException以及它的子类*/
// Java编译期异常必须处理,否则编译器会提示错误,且源文件无法成功编译 // 处理方法两种 // 1.使用try_catch_finally关键字捕获并处理 // 2.使用throws关键字声明抛出异常,让别人去处理
在try_catch_finally这三个语句块中分别执行return会有不同的细节,上代码!
package SE02.n1Exception; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class Demo03Retrun { public static void main(String[] args) { System.out.println(test1()); // System.out.println(test2()); // System.out.println(test3()); // System.out.println(test4()); } private static String test1() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); String string="1000年2月2日";//代码正常,可以被正常年月日格式化 String rStr="begin"; try { Date d=sdf.parse(string);//需异常处理 return rStr;//上一条报错,此条不可达,不运行 }catch(ParseException e){ rStr="catch"; return rStr;//先封存,再finally,再return封存 }finally { rStr="finally"; return rStr; }当return写在finally代码块中时,无论是无异常还是有异常,最后返回的都是“finally” 接下来进行分类讨论: (1)当try语句中的代码无异常: try中的return rStr不会立马执行,会将rStr的内存地址封存在一个空间中,等finally代码块执行完才会return封存的内存地址,再根据内存地址寻找要输出的字符串。但是,当finally代码块中有return关键字时,程序会优先执行finally代码块中的return关键字,try语句块中的return封存的内存地址将被永久封存,return的是finally代码块中的rStr。 (2)当try语句中的代码需要异常处理: 同样的是封存try中的return,进入catch,再对catch中的return进行封存,最后执行finally中的代码块,若finally中有return语句,则执行finally中的return语句,而try和catch中return封存的值将永久封存,最终输出finally中的return。 所以上面代码输出的结果为:finally
话不多说先上代码!
private static String test1() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); String string="2000年2月2日";//该字符串在格式化年月日时不会抛出异常,格式正确 String rStr="begin"; try { Date d=sdf.parse(string);//不需要异常处理 return rStr;//此条可达,执行 }catch(ParseException e){ rStr="catch"; return rStr;//先封存,再finally,再return封存 }finally { System.out.println("这里是finally代码块"); } }先上输出结果: 这里是finally代码块 begin 语句依次执行try—>catch—>finally。在执行try时:Date d=sdf.parse(string)执行完毕后,执行return语句,封存rStr的内存地址(begin),跳过catch语句块,执行finally语句块中的输出语句,最后return封存中的begin
private static String test1() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); String string="2000年2月2日";//该字符串在格式化年月日时会抛出异常,非正确格式 String rStr="begin"; try { Date d=sdf.parse(string);//需要异常处理 return rStr;//此条不可达,不执行 }catch(ParseException e){ rStr="catch"; return rStr;//先封存,再finally,再return封存 }finally { System.out.println("这里是finally代码块"); } }先上输出结果: 这里是finally代码块 finally 同样,语句依次执行try—>catch—>finally。在执行try时:Date d=sdf.parse(string)会抛出异常,从而导致直接跳进catch语句块,使return不可达。进入catch语句后:此时rStr重新赋值。(注意!java中String类型的对象是固定的不变的,在本人的其他博客中有详细介绍String类型)此时的rStr和最开始定义的String rStr="begin"的内存地址是不同的,虽然变量名相同,但内存地址不同,这里的return封存的就是内存地址,所以现在封存的是catch。最后执行finally代码块的输出语句,再return rStr。
先上结果: finally 3 同样如果finally中有return,不管try和catch中的封存,直接执行return中的封存。
private static int test2() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); String string="100年2月2日"; int i =0; try { Date d=sdf.parse(string);//需异常处理 i=1; return i; }catch(ParseException e){ System.out.println("catch"); i=2; System.out.println("ii"); return i;//先封存(基本数据类型的值)(八种数据类型的值可以直接放在栈中),再finally,再return封存 }finally { i=3; System.out.println("finally"); } }先上结果: finally 1 需要注意的是:finally代码块中虽然i被重新赋值,但是try中的return已经率先封存了i=1的内存地址,所以… 与String类型相似的是:先封存(基本数据类型的值)(八种数据类型的值可以直接放在栈中),再finally,再return封存
自己新建一个Class:Person类 令try_catch语句的返回值为Person
先上结果: catch finally Person [age=12] 由于封存的都是p的内存地址,所以每次p的属性被重新赋值都会改变封存中的内容。所以如果finally中有有关p对象的赋值语句,return中的封存内容就会被改写(内存地址值不变)。
private static Person test3() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); String string="20**年2月2日"; Person p =new Person(); try { Date d=sdf.parse(string);//需异常处理 System.out.println("try"); }catch(ParseException e){ p.age=12; System.out.println("catch"); return p;//先封存(引用的地址值),再finally,再return封存 }finally { p.age=11; System.out.println("finally"); } return p; }先上输出结果: catch finally Person [age=11]
当finally中有赋值语句,就会改写封存内容
先上结果: finally 原因:finally中出现return,其他语句块的封存全部失效
private static StringBuilder test4() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); String string="100#0年2月2日"; StringBuilder rStr=new StringBuilder("begin"); try { Date d=sdf.parse(string);//需异常处理 return rStr;//上一条报错,此条不可达,不运行 }catch(ParseException e){ rStr.append("catch"); return rStr;//先封存,再finally,再return封存 }finally { rStr.append("finally"); } } }注:有关StringBuilder的相关介绍和方法介绍在本人其他博客中有详解,请客官移步。 先上输出结果:begincatchfinally 从输出结果中可以看出,rStr游历了所有语句块,同样的是return封存了内存地址,而rStr对象中的属性改变,return出的rStr依旧会是append后的结果