A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 張帅 中级黑马   /  2013-9-26 08:23  /  2570 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class Demo
{
           public static void main(String[] args)
           {
               try
             {
                 showExce();
                 System.out.println("A");
             }
            catch(Exception e)
           {
                  System.out.println("B");
           }
            finally
         {
                System.out.println("C");
           }
           System.out.println("D") ;
        }

        public static void showExce() throws Exception
        {
                throw new Exception();
        }
}
//这个执行的结果为什么为B C D,而 如果把主函数中try语句中的showExce()方法改为throw new Exception();就会编译失败,有什么区别吗?

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

5 个回复

倒序浏览
try
             {
                 showExce();
                 System.out.println("A");
             }
如果 showExce()方法抛出了异常,try代码块中 showExce()后面的代码是不会被执行的,这是try语句的流程。
从流程上看,如果try代码块中抛出了异常,程序会执行catch语句,finally语句,如果没有其他控制,会继续之后的代码。
但是如果在try语句中直接throw new Exception(),会编译失败,因为此句后面的代码肯定执行不到。把throw new Exception()放在方法中,再调用方法ok。因为编译时不会检查方法中是不是只有一句抛出语句,只进行语法检查。运行时,到了抛出异常的代码,就进入了try语句的流程。
回复 使用道具 举报
楼上分析的已经很有道理,我来分享些异常处理机器的一些经验。希望对您有帮助哦!

为什么要声明方法抛出异常?
      方法是否抛出异常与方法返回值的类型一样重要。假设方法抛出异常确没有声明该方法将抛出异常,那么客户程序员可以调用这个方法而且不用编写处理异常的代码。那么,一旦出现异常,那么这个异常就没有合适的异常控制器来解决。
③ 为什么抛出的异常一定是已检查异常?
      RuntimeException与Error可以在任何代码中产生,它们不需要由程序员显示的抛出,一旦出现错误,那么相应的异常会被自动抛出。而已检查异常是由程序员抛出的,这分为两种情况:客户程序员调用会抛出异常的库函数(库函数的异常由库程序员抛出);客户程序员自己使用throw语句抛出异常。遇到Error,程序员一般是无能为力的;遇到RuntimeException,那么一定是程序存在逻辑错误,要对程序进行修改(相当于调试的一种方法);只有已检查异常才是程序员所关心的,程序应该且仅应该抛出或处理已检查异常。
      注意:覆盖父类某方法的子类方法不能抛出比父类方法更多的异常,所以,有时设计父类的方法时会声明抛出异常,但实际的实现方法的代码却并不抛出异常,这样做的目的就是为了方便子类方法覆盖父类方法时可以抛出异常。

如何抛出异常
① 语法:throw(略)
② 抛出什么异常?对于一个异常对象,真正有用的信息时异常的对象类型,而异常对象本身毫无意义。比如一个异常对象的类型是ClassCastException,那么这个类名就是唯一有用的信息。所以,在选择抛出什么异常时,最关键的就是选择异常的类名能够明确说明异常情况的类。
③ 异常对象通常有两种构造函数:一种是无参数的构造函数;另一种是带一个字符串的构造函数,这个字符串将作为这个异常对象除了类型名以外的额外说明。
④ 创建自己的异常:当Java内置的异常都不能明确的说明异常情况的时候,需要创建自己的异常。需要注意的是,唯一有用的就是类型名这个信息,所以不要在异常类的设计上花费精力。

捕获异常
      如果一个异常没有被处理,那么,对于一个非图形界面的程序而言,该程序会被中止并输出异常信息;对于一个图形界面程序,也会输出异常的信息,但是程序并不中止,而是返回用错误页面。
      语法:try、catch和finally(略),控制器模块必须紧接在try块后面。若掷出一个异常,异常控制机制会搜寻参数与异常类型相符的第一个控制器随后它会进入那个catch 从句,并认为异常已得到控制。一旦catch 从句结束对控制器的搜索也会停止。
      捕获多个异常(注意语法与捕获的顺序)(略)
      finally的用法与异常处理流程(略)
      异常处理做什么?对于Java来说,由于有了垃圾收集,所以异常处理并不需要回收内存。但是依然有一些资源需要程序员来收集,比如文件、网络连接和图片等资源。
      应该声明方法抛出异常还是在方法中捕获异常?原则:捕捉并处理哪些知道如何处理的异常,而传递哪些不知道如何处理的异常。
再次抛出异常
①为什么要再次抛出异常? 在本级中,只能处理一部分内容,有些处理需要在更高一级的环境中完成,所以应该再次抛出异常。这样可以使每级的异常处理器处理它能够处理的异常。
②异常处理流程 :对应与同一try块的catch块将被忽略,抛出的异常将进入更高的一级。



4 关于异常的其他问题
① 过度使用异常 :首先,使用异常很方便,所以程序员一般不再愿意编写处理错误的代码,而仅仅是简简单单的抛出一个异常。这样做是不对的,对于完全已知的错误,应该编写处理这种错误的代码,增加程序的鲁棒性。另外,异常机制的效率很差。
② 将异常与普通错误区分开:对于普通的完全一致的错误,应该编写处理这种错误的代码,增加程序的鲁棒性。只有外部的不能确定和预知的运行时错误才需要使用异常。
③ 异常对象中包含的信息 :一般情况下,异常对象唯一有用的信息就是类型信息。但使用异常带字符串的构造函数时,这个字符串还可以作为额外的信息。调用异常对象的getMessage()、toString()或者printStackTrace()方法可以分别得到异常对象的额外信息、类名和调用堆栈的信息。并且后一种包含的信息是前一种的超集。


评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
当然有区别啊:
上面代码中调用showExce();函数,而这个函数此时抛出了异常对象,此时抛出异常就不会执行try中剩下的代码了;
下面catch语句中就能进行捕捉,也就catch语句中的语句就已经被执行了;
最后finally也是必须要执行的。所以结果使BCD就很正常了。
至于throw new Exception()这是直接给出了异常对象,在程序的任何部分都不能出现,因为被封装的showExce()函数上面有throws Exception,并且函数内部封装了什么都不知道的,只是函数有可能会发生异常,而throw new Exception()不能将异常对象网外抛,直接把异常给了try语句,也就是铁定有异常,所以编译时期会检查出来。

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
   try
              {
                  showExce();
                  System.out.println("A");
              }
这样写不会报编译错误,
   try
              {         
                  throw new Exception();
                  System.out.println("A");
              }
这样写机会报编译错误。具体是因为:
第一种写法是在try代码块中调用了一个函数,虽然这个函数是直接抛出了异常,但是,虚拟机检查的时候,只会认为这个方法可能会发生异常,所以后面的打印语句可能会输出,所以编译会通过。
而第二种写法是在try代码块中直接先抛出异常,再打印。这显然是编译通不过的,因为当抛出异常后,throw后面的打印语句不会再执行,虚拟机不允许这样的操作,所以编译不会通过。

希望可以帮助你~

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
  1. class Demo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 try
  6.                 {
  7.                         showExce();
  8.                         System.out.println("A");
  9.                 }
  10.                 catch(Exception e)
  11.                 {
  12.                         System.out.println("B");
  13.                 }
  14.                 finally
  15.                 {
  16.                         System.out.println("C");
  17.                 }
  18.                 System.out.println("D") ;
  19.         }

  20.         public static void showExce() throws Exception
  21.         {
  22.                 throw new Exception();
  23.         }
  24. }
复制代码
从你的代码可以看出来,showExce()方法中抛出一个异常,但是你的方法体上写了把这个异常继续往上抛,public static void showExce() throws Exception这句话的意思就是,有任何的异常交由我的上一级方法进行处理,他的上一级就是
try
                {
                        showExce();
                        System.out.println("A");
                }
所以由try处理异常,最终由catch捕获到异常,进行
catch(Exception e)
                {
                        System.out.println("B");
                }
输出操作,然后执行finally块的内容。所以并不会有任何异常抛出,因为你已经对异常进行了处理,如果在这里public static void showExce() throws Exception不加throws Exception,那么它抛出的异常没有处理就会交由虚拟机处理,结果肯定是报异常,程序终止。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马