第五章 异常Exception


第一节 异常(Exception)

1.异常(Exception)的定义,意义和用法 (视频下载) (全部书籍)

我们先给出一个例子,看看异常有什么用?



例:1.1-本章源码

public class Test {
    public static void main(String[] args) {
        int userInput=0;
        int I = 6 / userInput;
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.main(Test.java:4)


例:1.1.2-本章源码

public class Test {
    public static void main(String[] args) {
        try
        {
            int userInput=0;
            int I = 6 / userInput;
            System.out.println("马克-to-win:inside try");
        }
/*系统把错误信息放在Exception的对象e中,马克-to-win*/        
        catch(Exception e)
        {
            System.out.println(e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

java.lang.ArithmeticException: / by zero
马克-to-win:优雅结束

异常的意义:马克-to-win: (视频下载) (全部书籍)通过上面的例子,我们看出通过引入异常这种技术,即使出现不测(用户把0赋给除数),也可以让程序不崩溃,还能继续优雅的运行。那,这种技术有用,值得学。马克-to-win:当你批量下载文件时,如出现什么错误,你是不是希望下载器能告诉你出现了什么问题,比如硬盘不足等等,在你提供了足够的硬盘空间以后,下载继续自动进行。而不是说空间一不足,立刻下载器就崩溃呀!这就是异常技术。

异常这种技术框架是怎么工作的?【新手可忽略不影响继续学习】 (视频下载) (全部书籍)马克-to-win:注意是运行程序时,而不是编译时,当一个非正常情况出现,比如除0,就叫异常情况。马克-to-win:为了能优雅的处理异常情况(在出现异常情况后,程序不崩溃,还能继续优雅的运行), Sun公司设计了异常技术框架,马克-to-win:你把可能出现问题的语句放在try块儿中,真出了问题的话,系统会把问题的信息存放在一个异常类的对象中传入到catch块中,在catch块儿中,你可以专门根据错误信息作处理。这样业务代码放在try块儿中,错误处理代码放在catch中,好处是易读,条理清楚。马克-to-win:没有try catch这种异常技术前,业务代码和排错代码是搅和在一起的!

我怎么知道哪块代码可能出现问题,从而放在try块儿中呢? (视频下载) (全部书籍)马克-to-win:一个笨办法,开始时,你并不加try,但你发现,运行时,用户赋给除数一个0,所以程序在这崩溃了,于是你就把这块代码加个try,过两天,用户又犯了一个数组越界的错误,致使程序崩溃了。马克-to-win:你又加了个try,久而久之,你的try块儿就会变得越来越大,你的代码就会变得越来越健壮。马克-to-win:再往后,你就有经验了,你自然知道常规的,只要用户可以赋给除数值时,就应该放在try块儿当中。

我怎么知道应该捕获什么样的异常? (视频下载) (全部书籍)马克-to-win:如上例1.1:开始没加try时,程序崩溃,系统打印的是如下的错误,Exception in thread "main" java.lang.ArithmeticException: / by zero at Test.main(Test.java:4),马克-to-win: 所以我们就该捕获ArithmeticException.见下例:1.1.3。

例:1.1.3-本章源码

public class Test {
    public static void main(String[] args) {
        try
        {
            int userInput=0;
            int I = 6 / userInput;
        }
        catch(ArithmeticException e)
        {
            System.out.println(e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

java.lang.ArithmeticException: / by zero
马克-to-win:优雅结束

顺便提一句, (视频下载) (全部书籍)和Exception相对应的,还有Error,Error(错误)表示系统级的错误和程序不必处理的异常,是JRE(java运行环境)的内部错误或者硬件问题,比如,另外某一处地方的bug引起的内存溢出,内存资源不足等,OutOfMemoryError,对这类错误,程序基本无能为力,比如下例中,catch不被执行(其实虚拟机是有能力执行的,否则finally为什么被执行?但就是这原则,意味着,程序员们不要试图在catch中做什么,你做了, 我也不执行,因为是Error,而不是Exception)只能退出。

例:

public class Test {
/* maxMemory将返回java虚拟机所能返回的最大可用内存。0.92可以, 0.93就报错 */
    int size_Make_to_win = (int) (Runtime.getRuntime().maxMemory() * 0.93);
    public void allo() {
        byte[] data1 = new byte[size_Make_to_win];
    }
    public static void main(String[] args) {
        Test t = new Test();
        try{
        t.allo();
        }
        catch(Exception e)
        {
            System.out.println(e+"qqq");
        }
        finally
        {
            System.out.println("in finally");
        }

    }
}

输出结果:

in finally
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at Test.allo(Test.java:5)
    at Test.main(Test.java:10)


2.多重捕获MultiCatch  (视频下载) (全部书籍)

马克-to-win:什么叫多重捕获MultiCatch?一段代码可能引起多个异常,这时可以定义两个或更多的catch子句来处理这种情况,每个子句捕获一种类型的异常。马克-to-win:异常被引发时,每一个catch块儿被依次检查,第一个匹配异常类型的catch块儿被执行。马克-to-win:当一个catch块儿执行以后,其他的catch块儿被跳过,继续try/catch块以后的代码。像switch一样。



例:1.2.1-本章源码
public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
        String s="abc";
    //    String s="12";
        try {
            arg1 = Integer.parseInt(s); //马克-to-win:这里会发生异常,所以try块中后面语句执行不了, 进入catch 块儿
            result = arg1 /0;
            System.out.println("try部分没有完成,所以打印不出这里");
        }
        catch (NumberFormatException e) {
            System.out.println("输入参数必须为整数!");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

输入参数必须为整数!
马克-to-win:优雅结束


观察上一个例子可知:用户根据提示,输入会变成整数,见下一个例子。

例:1.2.2-本章源码

public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
    //    String s="abc";
        String s="12";
        try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;//马克-to-win:这里会再次抛出异常,使程序崩溃
            System.out.println("try中完成finish");
        }
        catch (NumberFormatException e) {
            System.out.println("输入参数必须为整数!");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:


Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.main(Test.java:9)

观察例1.2.2可知:马克-to-win:由于我们少捕获一个除0异常,程序崩溃, 很可怕。程序进一步修改如下:

例:1.2.3-本章源码

public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
    //    String s="abc";
        String s="12";
        try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;
            System.out.println("try中完成finish");
        }
        catch (NumberFormatException e) {
            System.out.println("输入参数必须为整数!");
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        }

        System.out.println("马克-to-win:优雅结束");
    }
}

结果如下:

除数不能为0
马克-to-win:优雅结束

马 克-to-win:程序又一次在出现问题的情况下,优雅结束了。上例中蓝色部分是多重捕获catch。马克-to-win:观察上面三个例子,结论就是即 使你已经捕获了很多异常,但是假如你还是少捕获了什么异常,赶上那个异常发作,你程序还是会崩溃的。马克-to-win:但是有读者说,我的经验就是不足,老是少捕获什么异常,那怎么办呀?我们可以求助于下一节的技术,Exception类捕获所有的异常。

马克-to-win: (视频下载) (全部书籍)程序又一次在出现问题的情况下,优雅结束了。上例中蓝色部分是多重捕获catch。马克-to-win:观察上面三个例子,结论就是即使你已经捕获了很多异常,但是假如你还是少捕获了什么异常,赶上那个异常发作,你程序还是会崩溃的。马克-to-win:但是有读者说,我的经验就是不足,老是少捕获什么异常,那怎么办呀?我们可以求助于下一节的技术,Exception类捕获所有的异常。

3.用Exception类捕获所有异常  (视频下载) (全部书籍)
马克-to-win:注意,一个事实是:Exception类是所有其他异常类的父类,所以Exception类能捕获所有的异常。马克-to-win:问题是用Exception来捕获所有的异常,这个技术有什么好处和缺点?好处就是:不管发生什么异常,都能进入Exception catch块儿,这样,程序都不崩溃。马克-to-win:缺点就是:不能根据特定的异常做特定的处理。马克-to-win:比如,对于以上例子,我们可以用以下的技术,Exception来捕获所有的异常,都可以达到程序不崩溃的目的。马克-to-win:因为Exception是所有其他异常的父类。



例:1.3.1-本章源码
public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
        String s="abc";
    //    String s="12";
        try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;
            System.out.println("try中完成finish");
        }
        catch (Exception e) {
            System.out.println(e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:
java.lang.NumberFormatException: For input string: "abc"
马克-to-win:优雅结束

例:1.3.2-本章源码
public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
    //    String s="abc";
        String s="12";
    
try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;
            System.out.println("try中完成finish");
        }
        catch (Exception e) {
            System.out.println(e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}
输出结果:
java.lang.ArithmeticException: / by zero
马克-to-win:优雅结束

马克-to-win:注意Exception虽然能够捕获所有的异常,使程序不崩溃(“马克-to-win:优雅结束”可以被打印出 来)。马克-to-win:但是它不能像上一小节的多重捕获一样,根据特定的异常做特定的处理。马克-to-win:所以我们需要把这两种技术结合在一 起。见下例:

例:1.3.3-本章源码
public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
    //    String s="abc";
        String s="12";
        try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;
            System.out.println("try中完成finish");
        }
        catch (NumberFormatException e) {
            System.out.println("输入参数必须为整数!");
        }catch(Exception e){
            System.out.println("如有捕获不到的异常,我来! "+e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:
如有捕获不到的异常,我来! java.lang.ArithmeticException: / by zero
马克-to-win:优雅结束
 


4.当多重捕获MultiCatch和Exception相遇(对上节的总结)

马克-to-win:  (视频下载) (全部书籍)一个重要的技巧就是:catch多重异常时,子异常类必须在它们任何父类之前。马克-to-win:因为运用父类的catch语句将捕获该类型及其所有子类类型的异常。马克-to-win:这样,如果子类在父类后面,子类将永远不会到达。马克-to-win:你想写也不行,系统会报编译错误。


5.抛出throw关键字   (视频下载) (全部书籍)

马克-to-win:我们先说5/0的原理,当程序运行到5/0的时候,java系统JVM会在后台new出一个除0异常实例,之后把这个实例传入catch块儿供开发者使用马克-to-win:而这里throw new Exception();是开发者自己主动new出一个异常实例,之后把这个实例传入catch块儿供开发者自己使用。马克-to-win:对于catch来讲,不管谁抛的,处理起来都一样。

(新手必须忽略)意义是什么?见后面的sun的例子(1.5.4_a):if(url==null) throw new sqlException见例:1.5.4,这样就可以做到,有经验的人(这里是sun公司),预感到大家都易犯url==null这样的毛病(你开始不知道),于是他就throw new sqlException,(但是在sun公司写那段代码时,他又不能处理,因为逻辑上,就应该是你后来者的任务或说义务,举一个例子,爷爷规定遗产只能干教育,具体是生物还是物理或是数学他并不管,这里就是你必须管,但怎么管,怎么catch,你来做定夺,前人无法替你做决定)逼着你这个新手,必须catch这样的毛病,否则你的程序会崩溃。提醒你了,你不处理都不行。

例:1.5.1-本章源码

public class Test {
    public static void main(String[] args)  {
        int mark_to_win = 0;
        int c;
        if (mark_to_win == 0) throw new ArithmeticException("divide by 0");
        else c=8/mark_to_win;   
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.lang.ArithmeticException: divide by 0
    at Test.main(Test.java:5)


例:1.5.2-本章源码

public class Test {
    public static void main(String[] args)  {
        int mark_to_win = 0;
        int c;
        if (mark_to_win == 0)  c=8/mark_to_win;
        else c=8/mark_to_win;  
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.main(Test.java:5)

马 克-to-win:通过观察,我们发现上面两个例子最后报的异常的地方是一样的!异常的效果也是等价的!马克-to-win:如上面我们的讲的,只不过一 个是JVM系统抛出的,一个是我们自己主动抛出的。马克-to-win:所以为了不让系统崩溃,我们需要像原来一样捕获一下异常就可以了。

例:1.5.3-本章源码

public class Test {
    public static void main(String[] args)  {
        int mark_to_win = 0;
        int c;
        try{
            if (mark_to_win == 0) throw new ArithmeticException("divide by 0");
            else c=8/mark_to_win;            
        }catch(ArithmeticException a)
        {
            System.out.println(a);
        }
        System.out.println("马克-to-win:优雅结束");
      
    }
}

输出结果:

java.lang.ArithmeticException: divide by 0
马克-to-win:优雅结束


请大家参见下面sun公司的java.sql.DriverManager.getConnection的源代码。在我们的代码中, 我们也需要处理SQLException

例:1.5.4_a:


    private static Connection getConnection(
        String url, java.util.Properties info, Class<?> caller) throws SQLException {
        /*
         * When callerCl is null, we should check the application's
         * (which is invoking this class indirectly)
         * classloader, so that the JDBC driver class outside rt.jar
         * can be loaded from here.
         */
        ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
        synchronized(DriverManager.class) {
            // synchronize loading of the correct classloader.
            if (callerCL == null) {
                callerCL = Thread.currentThread().getContextClassLoader();
            }
        }

        if(url == null) {
            throw new SQLException("The url cannot be null", "08001");
        }



例:1.5.4(参考视频讲课用,新手必须忽略)

import java.sql.SQLException;

public class Test {
    public static void main(String[] args) throws
            ClassNotFoundException {
        java.sql.Connection connection = null;
        java.sql.Statement statement = null;
        java.sql.ResultSet resultSet = null;
        Class.forName("com.mysql.jdbc.Driver");
        try {
            connection = java.sql.DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/test", "root", "1234");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            statement = connection.createStatement();
            resultSet = statement.executeQuery("select * from login");
            while (resultSet.next()) {
                System.out.println(resultSet.getString("id") + "--"
                        + resultSet.getString("name"));
            }
            resultSet.close();
            statement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}




6.Checked Exception(受检的异常) (视频下载) (全部书籍)

马克-to-win:为什么我大胆的把Checked Exception翻译成受检的异常?因为这类异常,编译器检查发现到它后会强令你catch它或throws它(我们之后讲),马克-to-win:而相对于本节前面我们提到的各种比如ArithmeticException,都是unchecked exception(不受检)的异常,unchecked异常都是RuntimeException或者它的子类。马克-to-win:换句话:编译器检查发现到它以后,什么都不管,也什么都不做,直接放行。见下面的例子:

例:1.6.1-本章源码

public class Test {
    void m1_mark_to_win() {
        throw new RuntimeException("divide by 0");
    }
    public static void main(String[] args)   {
        Test t=new Test();
        t.m1_mark_to_win();
    }
}

输出结果:

Exception in thread "main" java.lang.RuntimeException: divide by 0
    at Test.m1_mark_to_win(Test.java:3)
    at Test.main(Test.java:7)


马克-to-win:注意上面一个例子ArithmeticException是个unchecked exception, 所以什么问题都没有,编译器不报错。马克-to-win:但是,当我们把ArithmeticException变成FileNotFoundException这种checked exception时,就会出现问题。马克-to-win:如下面例:1.6.2,根本就编译不过去。必须变成1.6.3才能运行。

例:1.6.2(编译报错,不能运行)-本章源码


import java.io.FileNotFoundException;

public class Test {
    void m1_mark_to_win() {
        throw new FileNotFoundException();
    }
    public static void main(String[] args)   {
        Test t=new Test();
        t.m1_mark_to_win();
    }
}

在throw new FileNotFoundException();外面,马克-to-win:必须包上一个try catch块儿,程序才能通过编译。

例:1.6.3-本章源码

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win() {
        try {
            throw new FileNotFoundException();
        } catch (FileNotFoundException e) {
            System.out.println(" in catch");
            e.printStackTrace();
        }
    }
    public static void main(String[] args)   {
        Test t=new Test();
        t.m1_mark_to_win();
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

 in catch
马克-to-win:优雅结束
java.io.FileNotFoundException
    at com.Test.m1_mark_to_win(Test.java:6)
    at com.Test.main(Test.java:14)

马克-to-win:checked和unchecked异常区别: (视频下载) (全部书籍)结论就是:1)RuntimeException和他的子类都是unchecked异常。其他的都是checked异常。马克-to-win:2)在编译阶段,编译器会检查每一个方法,看是否方法里面抛出了checked异常。假设抛出了checked异常,那个方法里必须加catch,或者加throws语句(下一节讲解),否则的话编译器会报错。马克-to-win:unchecked异常就没这规矩。

7.throws子句  (视频下载) (全部书籍)

马克-to-win:当你的方法里抛出了checked异常,如你不catch,代表你当时不处理(不想处理或没条件处理),但你必须得通过"throws那个异常"告诉系统说,这儿有个问题,我现在不处理,将来一定别人要处理,否则执行到它,马克-to-win:系统会"不优雅"的崩溃。举个例子,工兵张三发现了地雷,假如他处理,完事就完事儿了。但是他发现了地雷,自己却没带齐工具,没法处理,他必须做个标记,说这儿有一个地雷,别的工兵将来一定要处理,否则将来有人踩上去会爆炸。马克-to-win:注意:throws只是标记,并没处理,执行到那,系统还是会崩溃!

马克-to-win:语法总结就是:当你的方法里抛出了checked异常,如你不catch,必须throws,即告诉编译器,我的调用者会处理。如果你已经是main,则main的调用者jvm会替你收拾残局。否则无法编译通过。

马克-to-win:有的同学可能会问:throws有什么意义?又不真正处理问题。throws的意义,在于和throw配合起来一起工作。有关throw的意义,请参照上面throw部分。

马克-to-win:现在就出现了一个非常深入的问题。(新手可忽略)为什么sun公司的语法设计成:runtime异常不需要throws,而非runtime异常需要呢?咱们先说非runtime异常为什么需要throws呢?因为程序员多一道工序宣称一下,麻烦一下自己,会给sun公司的人(Java编译器)提供很大便利,少了很多判断等工作。说穿了就是麻烦我们自己方便他人。而为什么runtime异常不需要throws呢?因为运行时的情况非常复杂,程序员实在无法预料到所有的情况到底除零还是格式不对,所以即使想帮也帮不上忙。sun公司的人没有办法,只能自己去判断,即使再不愿意,也得干。于是也就不用你throws了。下面一段话摘自国外程序员和sun公司的对话:有关抱怨sun公司强迫他们写throws的,认为是个burden。挺有意思,大家可以看看。事儿(需要throws)都是programmer干的,出了问题,责任也是你的。


马克-to-win:拿上一节,1.6.2为例,当时有问题,我们用catch解决了,当然我们也可以用throws技术搞定它。


例:1.7.1(本例编译有错误)-本章源码

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win()  {
        throw new FileNotFoundException();
    }
}

马 克-to-win:上例编译有错误,因为FileNotFoundException是checked异常, 所以我们必须加catch马上处理或用throws留待将来处理。catch我们这里就不说了。马克-to-win:上节有论述。我们这里用throws 来处理。


例:1.7.2(可通过编译)-本章源码

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win() throws FileNotFoundException  {
        throw new FileNotFoundException();
    } 
}


像下面的子类也可以

例:1.7.2_2(可通过编译)-本章源码

import java.io.*;
public class Test {
    void m1_mark_to_win() throws IOException  {
        throw new FileNotFoundException();
    }
}

这里FileNotFoundException是IOException 的子类。

java.lang.Object
  java.lang.Throwable
   java.lang.Exception
    java.io.IOException
      java.io.FileNotFoundException


马 克-to-win:注意:例:1.7.2,编译就没问题了,但是throws FileNotFoundException,只是标记了一下问题,并没有真正处理,运行到throw new FileNotFoundException();时,程序还是会崩溃。马克-to-win:不信,下面我们就加一个主调方法测试一下。


例:1.7.3(本例编译有问题)-本章源码

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win() throws FileNotFoundException  {
        throw new FileNotFoundException();
    } 
    public static void main(String[] args)   {
        Test t=new Test();
        t.m1_mark_to_win();//这句会报红线
        System.out.println("马克-to-win:优雅结束");
    }
}

马 克-to-win:例:1.7.3的主调方法t.m1_mark_to_win();又有问题了,因为被调方法m1_mark_to_win()里面有一 个没有处理的throw异常,所以主调方法还是编译不过。马克-to-win:我们必须或者catch或者throws处理,catch上一节讲了,现在 我们不讲。这里我们用throws,等于还是没有处理,程序运行到这还是会崩溃。马克-to-win:下面我们看一下运行结果。

例:1.7.4-本章源码

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win() throws FileNotFoundException  {
        throw new FileNotFoundException();
    } 
    public static void main(String[] args) throws FileNotFoundException   {
        Test t=new Test();
        t.m1_mark_to_win();
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.io.FileNotFoundException
    at Test.m1_mark_to_win(Test.java:4)
    at Test.main(Test.java:8)


马克-to-win:结果分析:当程序运行t.m1_mark_to_win();程序崩溃了,连System.out.println("马克-to-win:优雅结束");都没有执行。要想不崩溃, 只能加try catch。

例:1.7.5-本章源码

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win() throws FileNotFoundException  {
        throw new FileNotFoundException();
    }
    public static void main(String[] args)   {
        Test t=new Test();
        try {
            t.m1_mark_to_win();
        } catch (FileNotFoundException e) {
            System.out.println(e);
        }

      System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

java.io.FileNotFoundException
马克-to-win:优雅结束

马克-to-win:下面的例子1.7.6,多了一层调用,道理是一样的, 仅供参考。一直用throws做缓兵之计,没有解决问题,所以程序最后还是崩溃了!catch才能真正解决问题。

例:1.7.6-本章源码

import java.io.FileNotFoundException;
class Class_mark_to_win
{
    void m1_mark_to_win() throws FileNotFoundException {
        throw new FileNotFoundException();
    }
}
class Class2_mark_to_win
{
    void m2_mark_to_win() throws FileNotFoundException {
        Class_mark_to_win c=new Class_mark_to_win();
        c.m1_mark_to_win();
    }
}
public class Test {
    public static void main(String[] args) throws FileNotFoundException    {
        Class2_mark_to_win c2=new Class2_mark_to_win();
        c2.m2_mark_to_win();
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.io.FileNotFoundException
    at Class_mark_to_win.m1_mark_to_win(Test.java:5)
    at Class2_mark_to_win.m2_mark_to_win(Test.java:12)
    at Test.main(Test.java:20)


8.throws子句在继承当中overrride时的规则  (视频下载) (全部书籍)

马克-to-win:当子类方法override父类方法时,throws子句不能引进新的checked异常。换句话说:子类override方法的throws子句checked异常不能比父类多。马克-to-win:上面一条是死语法规定,这种规定,实际上都是源于checked异常这种最初的设计。

例:1.8.1-本章源码

import java.io.IOException;
class Animal{
    void call() throws IOException
    {
        System.out.println("Animal");
    }
}
class Dog extends Animal{
    void call() throws IOException
    {
        System.out.println("Dog");
    }
}

public class Test {
    public static void main(String args[]) throws IOException {
        Dog d = new Dog();
        d.call();
    }
}

输出结果:

Dog


马克-to-win:为了让读者更加清楚一点,现在我们假象程序员在编Dog的时候就突发奇想想加一个SQLException,会发生什么?

例:1.8.2(有问题不能编译)-本章源码

import java.io.IOException;
import java.sql.SQLException;
class Animal{
    void call() throws IOException
    {
        System.out.println("Animal");
    }
}
class Dog extends Animal{
    /*马克-to-win:这里报错说父类的throws得加上SQLException,Exception SQLException is not compatible with throws clause in Animal.call()*/    
    void call() throws IOException, SQLException
    {
        System.out.println("Dog");
    }
}

public class Test {
    public static void main(String args[]) throws IOException {
        Dog d = new Dog();
        d.call();
    }
}




9.创建自定义异常 Create Custom Exception  (视频下载) (全部书籍)

马克-to-win:我们可以创建自己的异常:checked或unchecked异常都可以, 规则如前面我们所介绍,反正如果是checked异常,则必须或者throws,或者catch。到底哪个好,各路架构师大神的意见是50对50。见我本章后面的附录。sun公司开始说,checked异常可以使你的系统异常语义表达很清楚。但很多人经过一段时间的实践后,马上表示了异议。checked异常是java独有的,但连Thinking in java的作者都表示,checked异常作为一种java特有的实验行为,不是很成功。我个人的意见是:为了达到解耦的目的,最好继承unchecked异常。否则你各种业务方法都得throws。将来业务方法一旦改变,还得考虑处理这些throws。(新手可忽略)比如你的业务方法a里如果新加了一句throw受检异常,而且你还没有catch,则调用你这个a方法的客户程序将必须或者catch或者throws,反正必须做出相应调整。如果当初你的a方法里只是抛出一个非受检异常,客户程序就不用做任何调整了。

例1.9.1-本章源码

public class Test {
    public static void main(String args[]) throws RelationshipExceptionMark_to_win {
        int talkTimesPerDay = 2;
        if (talkTimesPerDay < 3) {
            RelationshipExceptionMark_to_win e = new RelationshipExceptionMark_to_win();
            e.setMsg("每天说话小于3 次,抛出关系异常的异常,分手");
            System.out.println("马克-to-win:here");
            throw e;
        }
        System.out.println("马克-to-win:优雅结束");
    }
}
class RelationshipExceptionMark_to_win extends Exception {
    String msg;
    String getMsg() {
        return msg;
    }
    void setMsg(String msg) {
        this.msg = msg;
    }
}

输出结果:

马克-to-win:here
Exception in thread "main" RelationshipExceptionMark_to_win
    at Test.main(Test.java:5)


例1.9.2-本章源码

public class Test {
    public static void main(String args[]) {
        int talkTimesPerDay = 2;
        if (talkTimesPerDay < 3) {
            RelationshipExceptionMark_to_win e = new RelationshipExceptionMark_to_win();
            e.setMsg("每天说话小于3 次,抛出关系异常的异常,分手");
            throw e;
        }
        System.out.println("马克-to-win:优雅结束");
    }
}
class RelationshipExceptionMark_to_win extends RuntimeException {
    String msg;
    String getMsg() {
        return msg;
    }
    void setMsg(String msg) {
        this.msg = msg;
    }
}


输出结果:

Exception in thread "main" RelationshipExceptionMark_to_win
    at Test.main(Test.java:5)



例1.9.3-本章源码

public class Test {
    public static void main(String args[]) {
        int talkTimesPerDay = 2;
        try {
            if (talkTimesPerDay < 3) {
                RelationshipExceptionMark_to_win e = new RelationshipExceptionMark_to_win();
                e.setMsg("每天说话小于3 次,抛出关系异常的异常,分手");
                throw e;
            }
        } catch (RelationshipExceptionMark_to_win e1) {
            System.out.println(e1.getMsg());
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

class RelationshipExceptionMark_to_win extends Exception {
    String msg;
    String getMsg() {
        return msg;
    }

    void setMsg(String msg) {
        this.msg = msg;
    }
}

输出结果:

每天说话小于3 次,抛出关系异常的异常,分手
马克-to-win:优雅结束

10.finally块  (视频下载) (全部书籍)

马克-to-win:finally块儿是怎么工作的?有什么意义?finally关键字创建一个代码块。没有try,finally块儿不能单独存在。该代码块在一个try/catch块完成之后另一个try/catch出现之前执行。马克-to-win:finally一定会执行,即使 1)异常没有发生 2)根本没有写catch块儿 3)没有与该异常相匹配的catch子句。4)try代码块中包含有break、continue、return或者throw语句(或直接崩溃或发生OutOfMemoryError)。

为什么抛出异常或发生错误,finally块儿还是能运行呢?想象一下程序执行的过程就明白了。jvm一句一句的向下执行,当它发现数组过界时,它就先执行finally块儿,然后再执行打印报错现在正在发生数组过界。注意现在是你的程序出现问题,jvm一点问题都没有,所以它还能正常打印报错。(见下面的例子)

马克-to-win: (视频下载) (全部书籍)finally有什么意义呢,在现实中?比如你开了一个流处理文件,可能没开成功,或开成功了,但后面的操作失败了,但不管你怎么样,你必须在一个地儿把它关闭,那就是finally块儿。

例: 1.10.1(try catch全齐,正常情况)-本章源码

public class Test {
    public static void main(String[] args) {
        try
        {
            int userInput=0;
            int I = 6 / userInput;
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
        finally
        {
            System.out.println("in finally");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

java.lang.ArithmeticException: / by zero
in finally
马克-to-win:优雅结束


例: 1.10.2(异常没有发生)-本章源码

public class Test {
    public static void main(String[] args) {
        try
        {
            int userInput=2;
            int I = 6 / userInput;
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
        finally

      {
            System.out.println("in finally");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}
输出结果:
in finally
马克-to-win:优雅结束


例: 1.10.3(根本没有写catch块儿)-本章源码

public class Test {
    public static void main(String[] args) {
        try
        {
            int userInput=2;
            int I = 6 / userInput;
        }
        finally
        {
            System.out.println("in finally");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

in finally
马克-to-win:优雅结束

例: 1.10.4(没捕获着异常,程序崩溃了)-本章源码

public class Test {
    public static void main(String[] args) {
        try {
            String str = null;
            str = str.toUpperCase();//本应捕获空指针异常
        } catch (ArithmeticException e) {//这里却想捕获数学异常, 完全捕不到
            System.out.println(e);
        }
        finally {//finally一定会被执行
            System.out.println("here is in final block.");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}
输出结果:

here is in final block.
Exception in thread "main" java.lang.NullPointerException
    at Test.main(Test.java:5)

例: 1.10.5(try代码中有throw或直接崩溃)-本章源码

public class Test {
    static void subRMark_to_win() {
        try {
            System.out.println("子程序");
            int a=1/0;
        }
        finally {
            System.out.println("子程序的finally");
        }
    }
    public static void main(String args[]) {
        try {
            subRMark_to_win();
        } catch (Exception e) {
            System.out.println("主程序的catch");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

子程序
子程序的finally
主程序的catch
马克-to-win:优雅结束


例: 1.10.6(try代码中有throw或直接崩溃)-本章源码

public class Test {
    static void subRMark_to_win() {
        try {
            System.out.println("子程序");
            throw new RuntimeException();
        }
        finally {
            System.out.println("子程序的finally");
        }
    }
    public static void main(String args[]) {
        try {
            subRMark_to_win();
        } catch (Exception e) {
            System.out.println("主程序的catch");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:
子程序
子程序的finally
主程序的catch
马克-to-win:优雅结束

例: 1.10.6_a(try代码中有OutOfMemoryError,依旧执行finally)

import java.util.Vector;

class Mark_to_win {
    long data;
}
public class Test {
    static Vector v = new Vector(10);
    static void subRMark_to_win() {
        try {
            System.out.println("子程序");
            int size_Make_to_win = (int) (Runtime.getRuntime().maxMemory() * 0.8);
            for (int i = 1; i < size_Make_to_win; i++) {
                Mark_to_win m = new Mark_to_win();
                v.add(m);
                m = null;
            }
        }
        finally {
            System.out.println("子程序的finally");
        }
    }
    public static void main(String args[]) {
        try {
            subRMark_to_win();
        } catch (Exception e) {
            System.out.println("主程序的catch");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}


输出:


子程序
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Unknown Source)
    at java.util.Arrays.copyOf(Unknown Source)
    at java.util.Vector.grow(Unknown Source)
    at java.util.Vector.ensureCapacityHelper(Unknown Source)
    at java.util.Vector.add(Unknown Source)
    at com.Test.subRMark_to_win(Test.java:16)
    at com.Test.main(Test.java:26)
子程序的finally

例: 1.10.7(try代码中有return)-本章源码

public class Test {
    static void subRMark_to_win() {
        try {
            System.out.println("子程序");
            return;
        }
        finally {
            System.out.println("子程序的finally");
        }
    }
    public static void main(String args[]) {
        try {
            subRMark_to_win();
        } catch (Exception e) {
            System.out.println("主程序的catch");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:
子程序
子程序的finally
马克-to-win:优雅结束

附录:本章源码 (视频下载) (全部书籍)

例:1.1

public class Test {
    public static void main(String[] args) {
        int userInput=0;
        int I = 6 / userInput;
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.main(Test.java:4)


例:1.1.2

public class Test {
    public static void main(String[] args) {
        try
        {
            int userInput=0;
            int I = 6 / userInput;
        }
    
        catch(Exception e)
        {
            System.out.println(e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

java.lang.ArithmeticException: / by zero
马克-to-win:优雅结束


例:1.1.3

public class Test {
    public static void main(String[] args) {
        try
        {
            int userInput=0;
            int I = 6 / userInput;
        }
        catch(ArithmeticException e)
        {
            System.out.println(e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

java.lang.ArithmeticException: / by zero
马克-to-win:优雅结束


例:1.2.1
public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
        String s="abc";
   
        try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;
            System.out.println("try部分没有完成,所以打印不出这里");
        }
        catch (NumberFormatException e) {
            System.out.println("输入参数必须为整数!");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:
输入参数必须为整数!
马克-to-win:优雅结束

例:1.2.2

public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
   
        String s="12";
        try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;
            System.out.println("try中完成finish");
        }
        catch (NumberFormatException e) {
            System.out.println("输入参数必须为整数!");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.main(Test.java:9)


例:1.2.3

public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
   
        String s="12";
        try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;
            System.out.println("try中完成finish");
        }
        catch (NumberFormatException e) {
            System.out.println("输入参数必须为整数!");
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        }

        System.out.println("马克-to-win:优雅结束");
    }
}

结果如下:

除数不能为0
马克-to-win:优雅结束


例:1.3.1
public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
        String s="abc";
   
        try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;
            System.out.println("try中完成finish");
        }
        catch (Exception e) {
            System.out.println(e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:
java.lang.NumberFormatException: For input string: "abc"
马克-to-win:优雅结束


例:1.3.2
public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
   
        String s="12";
        try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;
            System.out.println("try中完成finish");
        }
        catch (Exception e) {
            System.out.println(e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}
输出结果:
java.lang.ArithmeticException: / by zero
马克-to-win:优雅结束


例:1.3.3
public class Test {
    public static void main(String[] args) {
        int arg1;
        int result;
 
        String s="12";
        try {
            arg1 = Integer.parseInt(s);
            result = arg1 /0;
            System.out.println("try中完成finish");
        }
        catch (NumberFormatException e) {
            System.out.println("输入参数必须为整数!");
        }catch(Exception e){
            System.out.println("如有捕获不到的异常,我来! "+e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:
如有捕获不到的异常,我来! java.lang.ArithmeticException: / by zero
马克-to-win:优雅结束


例:1.5.1

public class Test {
    public static void main(String[] args)  {
        int mark_to_win = 0;
        int c;
        if (mark_to_win == 0) throw new ArithmeticException("divide by 0");
        else c=8/mark_to_win;   
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.lang.ArithmeticException: divide by 0
    at Test.main(Test.java:5)


例:1.5.2

public class Test {
    public static void main(String[] args)  {
        int mark_to_win = 0;
        int c;
        if (mark_to_win == 0)  c=8/mark_to_win;
        else c=8/mark_to_win;  
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.main(Test.java:5)


例:1.5.3

public class Test {
    public static void main(String[] args)  {
        int mark_to_win = 0;
        int c;
        try{
            if (mark_to_win == 0) throw new ArithmeticException("divide by 0");
            else c=8/mark_to_win;            
        }catch(ArithmeticException a)
        {
            System.out.println(a);
        }
        System.out.println("马克-to-win:优雅结束");
      
    }
}

输出结果:

java.lang.ArithmeticException: divide by 0
马克-to-win:优雅结束


例:1.6.1

public class Test {
    void m1_mark_to_win() {
        throw new RuntimeException("divide by 0");
    }
    public static void main(String[] args)   {
        Test t=new Test();
        t.m1_mark_to_win();
    }
}

输出结果:

Exception in thread "main" java.lang.RuntimeException: divide by 0
    at Test.m1_mark_to_win(Test.java:3)
    at Test.main(Test.java:7)

例:1.6.2(编译报错,不能运行)

public class Test {
    void m1_mark_to_win() {
        throw new FileNotFoundException();
    }
    public static void main(String[] args)   {
        Test t=new Test();
        t.m1_mark_to_win();
    }
}

在throw new FileNotFoundException();外面,马克-to-win:必须包上一个try catch块儿,程序才能通过编译。

例:1.6.3

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win() {
        try {
            throw new FileNotFoundException();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args)   {
        Test t=new Test();
        t.m1_mark_to_win();
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

java.io.FileNotFoundException
    at Test.m1_mark_to_win(Test.java:5)
    at Test.main(Test.java:12)
马克-to-win:优雅结束


例:1.7.1(本例编译有错误)

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win()  {
        throw new FileNotFoundException();
    }
}

马 克-to-win:上例编译有错误,因为FileNotFoundException是checked异常, 所以我们必须加catch马上处理或用throws留待将来处理。catch我们这里就不说了。马克-to-win:上节有论述。我们这里用throws 来处理。



例:1.7.2(可通过编译)

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win() throws FileNotFoundException  {
        throw new FileNotFoundException();
    } 
}


例:1.7.2_2(可通过编译)

import java.io.*;
public class Test {
    void m1_mark_to_win() throws IOException  {
        throw new FileNotFoundException();
    }
}

这里FileNotFoundException是IOException 的子类。

java.lang.Object
  java.lang.Throwable
   java.lang.Exception
    java.io.IOException
      java.io.FileNotFoundException


马 克-to-win:注意:例:1.7.2,编译就没问题了,但是throws FileNotFoundException,只是标记了一下问题,并没有真正处理,运行到throw new FileNotFoundException();时,程序还是会崩溃。马克-to-win:不信,下面我们就加一个主调方法测试一下。


例:1.7.3(本例编译有问题)

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win() throws FileNotFoundException  {
        throw new FileNotFoundException();
    } 
    public static void main(String[] args)   {
        Test t=new Test();
        t.m1_mark_to_win();
        System.out.println("马克-to-win:优雅结束");
    }
}

马 克-to-win:例:1.7.3的主调方法t.m1_mark_to_win();又有问题了,因为被调方法m1_mark_to_win()里面有一 个没有处理的throw异常,所以主调方法还是编译不过。马克-to-win:我们必须或者catch或者throws处理,catch上一节讲了,现在 我们不讲。这里我们用throws,等于还是没有处理,程序运行到这还是会崩溃。马克-to-win:下面我们看一下运行结果。



例:1.7.4

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win() throws FileNotFoundException  {
        throw new FileNotFoundException();
    } 
    public static void main(String[] args) throws FileNotFoundException   {
        Test t=new Test();
        t.m1_mark_to_win();
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.io.FileNotFoundException
    at Test.m1_mark_to_win(Test.java:4)
    at Test.main(Test.java:8)


例:1.7.5

import java.io.FileNotFoundException;
public class Test {
    void m1_mark_to_win() throws FileNotFoundException  {
        throw new FileNotFoundException();
    }
    public static void main(String[] args)   {
        Test t=new Test();
        try {
            t.m1_mark_to_win();
        } catch (FileNotFoundException e) {
            System.out.println(e);
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

java.io.FileNotFoundException
马克-to-win:优雅结束

例:1.7.6

import java.io.FileNotFoundException;
class Class_mark_to_win
{
    void m1_mark_to_win() throws FileNotFoundException {
        throw new FileNotFoundException();
    }
}
class Class2_mark_to_win
{
    void m2_mark_to_win() throws FileNotFoundException {
        Class_mark_to_win c=new Class_mark_to_win();
        c.m1_mark_to_win();
    }
}
public class Test {
    public static void main(String[] args) throws FileNotFoundException    {
        Class2_mark_to_win c2=new Class2_mark_to_win();
        c2.m2_mark_to_win();
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

Exception in thread "main" java.io.FileNotFoundException
    at Class_mark_to_win.m1_mark_to_win(Test.java:5)
    at Class2_mark_to_win.m2_mark_to_win(Test.java:12)
    at Test.main(Test.java:18)



例:1.8.1

import java.io.IOException;
class Animal{
    void call() throws IOException
    {
        System.out.println("Animal");
    }
}
class Dog extends Animal{
    void call() throws IOException
    {
        System.out.println("Dog");
    }
}
class Collie extends Dog{
    void call() throws IOException
    {
        System.out.println("Collie");
    }
}
class CallerMark_to_win {
 
    void test(Animal a)
    {
        try {
            a.call();
        } catch (IOException e) {
            System.out.println("捕获到IOException");
        }
    }
}
public class Test {
    public static void main(String args[]) throws IOException {
        CallerMark_to_win s = new CallerMark_to_win();
        Dog d = new Dog();
        Collie c=new Collie();
        s.test(d);
        s.test(c);
    }
}

输出结果:

Dog
Collie

例:1.8.2(有问题不能编译)

import java.io.IOException;
import java.sql.SQLException;
class Animal{
    void call() throws IOException
    {
        System.out.println("Animal");
    }
}
class Dog extends Animal{
    void call() throws IOException
    {
        System.out.println("Dog");
    }
}
class Collie extends Dog{
/*马克-to-win:这里报错说父类Dog的throws得加上SQLException,Exception SQLException is not compatible with throws clause in Dog.call()*/        void call() throws IOException, SQLException
    {  
        int a=8;
        System.out.println("Collie");
        if(a>4) throw new SQLException();
    }
}
class CallerMark_to_win {

    void test(Animal a)
    {
        try {
            a.call();
        } catch (IOException e) {
            System.out.println("捕获到IOException");
        }
    }
}
public class Test {
    public static void main(String args[]) throws IOException {
        CallerMark_to_win s = new CallerMark_to_win();
        Dog d = new Dog();
        Collie c=new Collie();
        s.test(d);
        s.test(c);
    }
}


例:1.8.3(有问题不能编译)
import java.io.IOException;
import java.sql.SQLException;
class Animal{
    void call() throws IOException, SQLException
    {
        System.out.println("Animal");
    }
}
class Dog extends Animal{
    void call() throws IOException, SQLException
    {
        System.out.println("Dog");
    }
}
class Collie extends Dog{
    void call() throws IOException, SQLException
    {  
        int a=8;
        System.out.println("Collie");
        if(a>4) throw new SQLException();
    }
}
class CallerMark_to_win {

    void test(Animal a)
    {
        try {
        
            a.call();
        } catch (IOException e) {
            System.out.println("捕获到IOException");
        }
    }
}
public class Test {
    public static void main(String args[]) throws IOException {
        CallerMark_to_win s = new CallerMark_to_win();
        Dog d = new Dog();
        Collie c=new Collie();
        s.test(d);
        s.test(c);
    }
}


例:1.8.4(下面这一般是正确的,终于修复了错误!)

import java.io.IOException;
import java.sql.SQLException;
class Animal{
    void call() throws IOException, SQLException
    {
       
        System.out.println("Animal");
        throw new IOException();
    }
}
class Dog extends Animal{
    void call() throws IOException, SQLException
    {
        System.out.println("Dog");
        throw new IOException();
    }
}
class Collie extends Dog{
    void call() throws IOException, SQLException
    {
        int a=8;
        System.out.println("Collie");
        if(a>4) throw new SQLException();
        if(a>4) throw new IOException();
    }
}
class CallerMark_to_win {
    void test(Animal a)
    {
        try {
            a.call();
        } catch (IOException e) {
            System.out.println("捕获到IOException");
        } catch (SQLException e) {
            System.out.println("捕获到SQLException");
        }
    }
}
public class Test {
    public static void main(String args[])  {
        CallerMark_to_win s = new CallerMark_to_win();
        Dog d = new Dog();
        Collie c=new Collie();
        s.test(d);
        s.test(c);
        System.out.println("马克-to-win:优雅结束");
    }
}

结果输出:

Dog
捕获到IOException
Collie
捕获到SQLException
马克-to-win:优雅结束


例1.8.5(正确)

import java.io.*;
import java.sql.SQLException;
class Superclass {
    void superMethod() throws IOException, SQLException {
    }
}
class Subclass extends Superclass {
    void superMethod() throws IOException, ArithmeticException,
            FileNotFoundException, SQLException {
    }
}

这里FileNotFoundException是IOException 的子类。

java.lang.Object
  java.lang.Throwable
   java.lang.Exception
    java.io.IOException
      java.io.FileNotFoundException

 


例1.9.1

public class Test {
    public static void main(String args[]) throws RelationshipExceptionMark_to_win {
        int talkTimesPerDay = 2;
        if (talkTimesPerDay < 3) {
            RelationshipExceptionMark_to_win e = new RelationshipExceptionMark_to_win();
            e.setMsg("每天说话小于3 次,抛出关系异常的异常,分手");
            throw e;
        }
        System.out.println("马克-to-win:优雅结束");
    }
}
class RelationshipExceptionMark_to_win extends Exception {
    String msg;
    String getMsg() {
        return msg;
    }
    void setMsg(String msg) {
        this.msg = msg;
    }
}

输出结果:

Exception in thread "main" RelationshipExceptionMark_to_win
    at Test.main(Test.java:5)


例1.9.2

public class Test {
    public static void main(String args[]) {
        int talkTimesPerDay = 2;
        if (talkTimesPerDay < 3) {
            RelationshipExceptionMark_to_win e = new RelationshipExceptionMark_to_win();
            e.setMsg("每天说话小于3 次,抛出关系异常的异常,分手");
            throw e;
        }
        System.out.println("马克-to-win:优雅结束");
    }
}
class RelationshipExceptionMark_to_win extends RuntimeException {
    String msg;
    String getMsg() {
        return msg;
    }
    void setMsg(String msg) {
        this.msg = msg;
    }
}

输出结果:

Exception in thread "main" RelationshipExceptionMark_to_win
    at Test.main(Test.java:5)


例1.9.3

public class Test {
    public static void main(String args[]) {
        int talkTimesPerDay = 2;
        try {
            if (talkTimesPerDay < 3) {
                RelationshipExceptionMark_to_win e = new RelationshipExceptionMark_to_win();
                e.setMsg("每天说话小于3 次,抛出关系异常的异常,分手");
                throw e;
            }
        } catch (RelationshipExceptionMark_to_win e1) {
            System.out.println(e1.getMsg());
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

class RelationshipExceptionMark_to_win extends Exception {
    String msg;
    String getMsg() {
        return msg;
    }

    void setMsg(String msg) {
        this.msg = msg;
    }
}

输出结果:

每天说话小于3 次,抛出关系异常的异常,分手
马克-to-win:优雅结束


例: 1.10.1(try catch全齐,正常情况)

public class Test {
    public static void main(String[] args) {
        try
        {
            int userInput=0;
            int I = 6 / userInput;
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
        finally
        {
            System.out.println("in finally");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

java.lang.ArithmeticException: / by zero
in finally
马克-to-win:优雅结束


例: 1.10.2(异常没有发生)

public class Test {
    public static void main(String[] args) {
        try
        {
            int userInput=2;
            int I = 6 / userInput;
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
        finally
        {
            System.out.println("in finally");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:
in finally
马克-to-win:优雅结束


例: 1.10.3(根本没有写catch块儿)

public class Test {
    public static void main(String[] args) {
        try
        {
            int userInput=2;
            int I = 6 / userInput;
        }
        finally
        {
            System.out.println("in finally");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

in finally
马克-to-win:优雅结束

例: 1.10.4(没捕获着异常,程序崩溃了)

public class Test {
    public static void main(String[] args) {
        try {
            String str = null;
            str = str.toUpperCase();
        } catch (ArithmeticException e) {
            System.out.println(e);
        }
        finally {
            System.out.println("here is in final block.");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}
输出结果:

here is in final block.
Exception in thread "main" java.lang.NullPointerException
    at Test.main(Test.java:5)


例: 1.10.5(try代码中有throw或直接崩溃)

public class Test {
    static void subRMark_to_win() {
        try {
            System.out.println("子程序");
            int a=1/0;
        }
        finally {
            System.out.println("子程序的finally");
        }
    }
    public static void main(String args[]) {
        try {
            subRMark_to_win();
        } catch (Exception e) {
            System.out.println("主程序的catch");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:

子程序
子程序的finally
主程序的catch
马克-to-win:优雅结束

例: 1.10.6(try代码中有throw或直接崩溃)

public class Test {
    static void subRMark_to_win() {
        try {
            System.out.println("子程序");
            throw new RuntimeException();
        }
        finally {
            System.out.println("子程序的finally");
        }
    }
    public static void main(String args[]) {
        try {
            subRMark_to_win();
        } catch (Exception e) {
            System.out.println("主程序的catch");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:
子程序
子程序的finally
主程序的catch
马克-to-win:优雅结束


例: 1.10.7(try代码中有return)

public class Test {
    static void subRMark_to_win() {
        try {
            System.out.println("子程序");
            return;
        }
        finally {
            System.out.println("子程序的finally");
        }
    }
    public static void main(String args[]) {
        try {
            subRMark_to_win();
        } catch (Exception e) {
            System.out.println("主程序的catch");
        }
        System.out.println("马克-to-win:优雅结束");
    }
}

输出结果:
子程序
子程序的finally
马克-to-win:优雅结束