static int f() {//这里报编译错误:must return a resutl of type int! int id = 0; int c = 3; try { return id; } catch (Exception e) { return c; } finally { System.out.println("finally"); } } 执行是先输出finally 再输出0
public static String getPath0_2() { File f = new File("e:\\"); try { int j = 3; String path = ""; path = f.getAbsolutePath(); return f.getAbsolutePath();//try中遇到return语句的话,先计算表达式的值,在finally,最后把刚才try中计算的值返回(注意,最后退出返回的时候不再重新计算)! } finally { f = null; } }
还真是!,不过我开始没看懂 我的代码 public static void main(String[] args) { System.out.println(getNum()); } public static int getNum() { int a=0; try { return a=3*6; } finally { System.out.println(a); a=10; } } 结果: 18 18
2.就是你说的这个顺序
按照这个顺序的话,无论有没有异常,catch之不执行,一定会执行finally,然后去找try中的return,也一定找的到,也就是无论有没有catch,都会finally,都能找到return!那你说“也就是不一定会执行return”是怎么得来的呢???谢谢!
在return还没有执行完,引发了异常,中断了return,进入了catch里。执行catch里的处理,这时候return并没有返回,而被中断了.所以你最终还是没有返回int.你可以在if块最后加上return 0;
如果你try中还未执行到return就抛出异常了,你到哪里去找return?
记住一点:当执行到return这一步语句的时候,让return等会,先执行finally{},完了再执行return,进行返回。(这样说应该够清楚了)如:
try{
语句1;
语句2;
语句3;
}catch(){
语句4;
}
finally{
语句5;
}
当语句1抛出异常时,执行顺序:1 4 5
当语句2抛出异常时,执行顺序:1 2 4 5
当语句1、2、3都没有异常时,执行顺序:1 2 3 5
问题一:try和catch是两个平行的分支,
LZ写的例子有可能对初学者有些不理解,就是return id不可能会抛异常。
举个例子:
try{
语句1;
return 返回结果;
}catch(){}finally{}
当语句1抛出异常后,"return 返回结果"这句就不会执行了,程序会跳到catch语句中,然后往执行,
请问像这样的话,这个方法不就没有返回结果了吗?!!!所以必须在catch语句里也要有个return语句。
----------
再回到LZ对第一个问题的疑问,
LZ既然写了catch语句,虽然说return id一般不会抛出异常,但是编译器对程序进行语法检测的时候,就认为程序会“有可能”走到catch语句块里的情况,所以报编译不通过。
而要是去掉catch语句块的话,程序只有一条路可走,所以编译器算是通过。
f2没有catch,try里面也没有会抛出非运行时异常(IOException,NumberFormatException)的代码,所以编译器认为try里面的return是有效的
------------你的意思是:有catch,则try中的return 没有效。没有catch,则try中的return 有效??? 不是吧。编译器是这样判断的??
2.如果有Error Exception则,执行catch(){}中的代码。
3.无论有没有 Error Exception都要执行finally{}中的代码。
4.执行 try 中的 return
-------------------------------------第四步骤不对!!
4 如果没有catch到异常,就finally,然后一定会找try中的return。如果catch到异常,就不会到try中去找return执行。----------为什么这么规定呢??因为:try中下边的代码是建立在try中上边的没有错误的基础上才执行的你写了catch,则说明try中的return之前的某一句代码可能异常,jvm这个时候就可能到catch中去。而到了catch中之后,try的抛出异常的代码之后的代码是根本不会执行的所以结果是:只要你写了catch,那么return是有可能不会执行到的。所以
1,编译错误,是在运行前按java语法,报的。
2,try-catch-finally,
如果try语句块遇到异常,try下面的代码就不执行了,转而执行catch语句块。
try-finally,
如果try语句块遇到异常,try下面的代码就不执行了.
但是上面2种情况,finally都会在之后被执行
3,return
只要执行了return就会立即结束方法(函数),即使finally没执行也一样。
所以,当JVM在try-catch中遇到return时,就会先执行finally,执行完finally后
再回过头来return.
---当然如果finally中也有return的话,就会执行这个return,并结束方法,
其他的return不会被执行。
关于1题:
try-catch-finally情况:
JVM不确定到底会不会执行catch{},所以强迫catch{},return。就会报编译错误
而try-finally情况:就不会报编译错误关于2题:
你可以用Eclipse设置个断点验证一下
附,我的测试代码
static Object f(){
int id = 0;
try {
System.out.println("before");
return id;
} catch (Exception e) {
//throw new Exception();
return 0;
} finally {
System.out.println(123);
return 2;
} 另外在补充一下:
return,和throw new Exception();效果差不多
都是会结束方法,并且都会返回值,(throw是让上一层“捕获到”)
一帮的执行顺序是:
1,执行try语句--》如果有异常,try中后面的语句都不会执行了。
2,catch捕捉异常,--》如果没有catch捕捉,程序退出
3,finally,总是要执行的,若try中有return,那么在return执行增强执行finally中的语句,若try和finally中都有return,那么在finally中执行return后程序结束,try中的return得不到执行
当然这是在方法不是void的情况下。
再帮你拓展一下,加深对这个知识点的认识。
你可以在try语句块中的任意一些地方,
试着加上这句:System.exit(1);
再看看程序运行的结果。。
比如下面的语句:
try {
return id;
} catch (Exception e) {}
你认为它不可能异常,肯定可以return。但编译器不管,它认为如果这个异常发生在return之前,你的这个方法就不能返回了。注意,它不会去检查你的return之前发生异常的可能性。它不是人,没那么聪明。
static int f() {//这里报编译错误:must return a resutl of type int!
int id = 0;
int c = 3;
try {
return id;
} catch (Exception e) {
return c;
} finally {
System.out.println("finally");
}
}
执行是先输出finally 再输出0
File f = new File("e:\\");
try {
int j = 3;
String path = "";
path = f.getAbsolutePath();
return f.getAbsolutePath();//try中遇到return语句的话,先计算表达式的值,在finally,最后把刚才try中计算的值返回(注意,最后退出返回的时候不再重新计算)!
} finally {
f = null;
}
}
我的代码
public static void main(String[] args) {
System.out.println(getNum());
}
public static int getNum() {
int a=0;
try {
return a=3*6;
} finally {
System.out.println(a);
a=10;
}
}
结果:
18
18
f()没有Catch()块 一定会执行到return语句 函数有返回值(至于能否返回正确的那是程序的逻辑问题 域编译无关)
f2()有catch()块 如果发生异常就执行不到return 函数没有了返回值(编译过不了)
编译的原理: 一定要保证程序可行 哪怕只有一种可能(像f2()有可能得不到返回值)
编程时应该先考虑用try-catch,而不是throws
捕获异常的格式:
try{
//可能发生异常的代码....
}catch(xxException e){
//异常发生以后处理的代码
}finally{
//不管发生不发生异常一定要执行的代码
}
finally可以出现1到N次,如果catch不出现就必须出现finally,catch出现了finally随便出现不出现
try只能出现一次,catch出现0-1次
它的运行顺序:
1,如果不发生异常时候执行try-finally
2,发生异常,try必定冲断,到catch
3,发生异常,try冲断到finally
4,发生异常,try冲断catch到finally继续运行下去,因为捕获了异常
try{
1
2
3
}catch(){
4
}
finally{
5
}
6
2若发生异常,则程序执行了1,2,4,5,6执行完毕
方法终结的3种,1,代码执行完了;2,执行到return ;3,有未捕获异常抛出也会终结
至于在finally块中出现了return/throw语句,那么原来的返回将不再执行。这种编程习惯不太好,容易造成一些很难发现的bug。
如果正常语句里有return finally里可以不必加return
如果正常执行语句里没有return finall里必须有return
1.try{}--finally{}
2.catch{}--finally{}
每条流程都必须有返回语句。若只有try{},没有catch{},则默认情况下是 发生异常时,先执行finally,最后在控制台输出错误信息,停止运行(相当于在catch中return)。试想,如果try中有return,catch中没有return,finally中没有return。当出现异常时,走的是第2条流程,catch虽然捕获了异常,但是没有返回值,且finally中也没有return,就是说一旦执行第2流程,则没有返回值。如果此时finally中有return的话,即使catch中没有return,也是可以的。
比如:
} catch (Exception e) {} finally {
return 1;
}
{
static int i = 0;
static void Main(string[] args)
{
int a = test();
//程序执行到这里,请问a和i的值分别为多少? } static int test()
{
try
{
return ++i;
}
catch
{
}
finally
{
i = 5;
}
return 100;
}
}
a=1;i=5也就是说把程序分为A.异常和B.正常:
A.此时再分为try异常和finally异常:1.先执行try,异常跳到catch
2.先执行try再到finally,finally异常跳到catch
B.正常时就先执行try,在执行finally,若finally中有return就返回一个值,以后不执行;若try中有return就返回try,返回一个值,return 100;不执行;若都没有就执行return 100;