Java 一个异常的问题

2017-04-19 06:12:14 +08:00
 esolve

class MyException extends Exception{

            public MyException (String str){
                    super(str);
            }
    }



    public class Test {

            static public void shout(int i) throws MyException{
                    if(i==0) throw new MyException("first");
            }


            public static void main(String[] args) {
                    System.out.println("in main "+call());
            }

            public static int call() {
                    int i = 100;

                    try{
                            System.out.println("before try");
                            shout(0);
                            System.out.println("after try!");
                            return i*5;
                            }
                    catch(RuntimeException e){
                            e.printStackTrace();
                            i*=2;
                            return i*10;
                    }
                    finally{
                            i++;
                            System.out.println("finally block, i is : "+i);
                            return i*3;
                    }
            }
    }

上列代码中, 26 行的 shout(0)抛出的 MyException 没有被捕捉,按理来说应该编译不通过 但是能通过编译 但是如果我把 38 行的 return i*3;注释掉,就编译不过了 怎么回事?

1898 次点击
所在节点    问与答
19 条回复
Sharuru
2017-04-19 08:05:48 +08:00
通俗点讲,你 catch 的是 Runtime Exception ,改成 Exception 或者 MyException 被你的异常捕获。

Finally 表示必执行的部分,既然 return int ,那么作为“最后保险” 必然需要 return ,异常发生时, try 内的 return 已经不会去执行,直接执行 catch 操作,若非 catch 对象则 finally 。
momocraft
2017-04-19 08:42:35 +08:00
我觉得 finally 中有 return 时能编译是正常的: 有异常又在 finally 中 return 时异常会被吞掉,不会向上传递

编译错误描述的是: 删去 `return i*3` 后 MyException 可能向上传递,但 call 又不 throws MyException 这个不一致

只要 finally 中"可能"不 return , javac 就会认为异常"可能"不被吞掉,并强制你 throws 。比如把 return i*3 改成 if (XX) return i*3; 会得到同样的编译错误。
sorra
2017-04-19 09:44:45 +08:00
竟然有这种事!虽然能解释,但语言设计上给人不合理的感觉。
h3nng
2017-04-19 10:15:06 +08:00
#1 楼基本解释清楚了,补充一句吧:为什么你自定义的 Exception 没捕获也能通过编译?因为你在 finally 里有 return 值,也就是说无论如何你的 call()这个方法,最终都是有返回值的,因此能通过编译;你没捕获只能认为你忽略了此异常(所以一般不建议在 finally 里 return ,这样异常就被忽略掉了)。
yeyuexia
2017-04-19 10:24:25 +08:00
@sorra 这不是 java 的问题 其他语言也都这样 年轻人先学会看文档再去想语言设计和不合理的问题再说
sorra
2017-04-19 12:21:32 +08:00
@yeyuexia 不知道您多大岁数,啥级别了,请教一下
sorra
2017-04-19 13:22:55 +08:00
@yeyuexia 看到你的技术分享还不错,但是说话别这么老气啊
yeyuexia
2017-04-19 13:41:30 +08:00
@sorra 你这个贴的问题明明白白是文档没读好的原因 甚至只要是看过一门带异常捕获的语言都会有解释的,然后就甩锅说语言设计不合理 那我只能理解你是新人零基础学编程了,建议多读读文档没什么问题吧?还有,没事干就让人亮岁数级别,现在这社会,是不是没宝马都没法教育人了 摊手
sorra
2017-04-19 14:10:31 +08:00
@yeyuexia 是你喊人年轻人,我就请你亮岁数级别嘛。现在你还居高临下说“教育人”

至于这个问题我是不同意你的意见的,我写 Java 也 5 年了, checked exception 本来就是有争议的,不要拿文档压人。你能从官方文档找出说明算我输。
yeyuexia
2017-04-19 15:13:03 +08:00
@sorra
catch 的用法 https://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html
RuntimeException https://docs.oracle.com/javase/7/docs/api/java/lang/RuntimeException.html
finally https://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
函数定义 https://docs.oracle.com/javase/tutorial/java/javaOO/returnvalue.html

顺便请教下 checked exception 本来就是有争议的 这句从何而来?

我还真是无聊啊 2333 五年的 JAVA …… 敢问阁下从哪高就呢?
sorra
2017-04-19 15:33:16 +08:00
@yeyuexia 你真的看了内容?哪里写了 return in finally block 的情况?哪里能教人避开楼主遇到的坑?
我告诉你我连语言规范都查了。
yeyuexia
2017-04-19 15:46:02 +08:00
专门给你贴了 return value 的连接 谢谢:)
sorra
2017-04-19 16:04:11 +08:00
@yeyuexia 原以为阁下有何高论,已全文阅读 return value 的链接,现在请你正面回答问题了。
附赠语言规范的链接 https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.20.2
Sharuru
2017-04-19 16:23:42 +08:00
早上上班路上等地铁时候无聊回答的问题,结果变成了撕逼 233 。
yeyuexia
2017-04-19 16:27:44 +08:00
@sorra 于是你想说什么呢? 这就是你函数不返回值的原因?还是你觉得 java 应该用 catch RuntimeException 来捕获 MyException ?
看完文档了还好意思在这继续扯 那我也没什么跟你扯淡的必要了。啧啧 java 五年
sorra
2017-04-19 16:29:18 +08:00
@yeyuexia 语言规范有一行文字能稍微支持你,加油找,找到了让你赢一半行不行?既然你继续装逼,我只能继续质疑你有没有阅读文档的能力了
yeyuexia
2017-04-19 16:33:43 +08:00
@sorra 哎呦喂 不写定义函数 return type 是 int 然后不写 return 编译不过去质疑 java 有问题,程序抛出了自己没有捕获异常是 java 有问题 您继续……我错了 我居然在五年 java 经验的大牛这质疑真是我的不是 233
请去翻翻书看看编译的时候在干什么好么 ? (认真脸)
sorra
2017-04-19 16:47:59 +08:00
我回复楼主的帖子,某个人来批判一番,口口声声叫人“先学会看文档”,自己恐怕根本没看过,一直不敢指出所谓的“文档”是哪一行文字。

现在揭晓答案吧:语言规范 https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.20.2 那行粗体文字

为什么说不合理呢?因为大部分人都不知道有这么危险的行为:在 finally 中 return ,不但会扰乱返回值,还会导致 checked exception 越过检查, javac 的编译是没有警告的,只有 IDE 给出了普通警告。官方教程没写,只有语言规范在一个小节提了一下,而且措辞比较绕。
esolve
2017-04-20 02:02:57 +08:00
@yeyuexia 我这里是故意抛出 RuntimeException 的,用来观察 catch 如果捕捉不到异常会如何表现

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/355768

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX