package com.javase.exception;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

/**
 * 异常的处理及异常发生后代码的执行顺序
 *      异常的处理方式:
 *          第一种:在方法声明的位置上,使用throws关键字向上抛出异常,谁调用我这个方法,我就抛给谁,抛给调用者来处理。
 *
 *             注意:java程序中发生异常以后如果一直上抛,最终抛给了main方法,main方法会抛给JVM,JVM会终止java程序的执行
 *                  一般在main方法上不建议使用throws。
 *
 *          第二种:使用try..catch语句对异常进行捕捉,对异常的处理到此为止,不再上报。
 *
 *            注意:只要异常没有被捕捉,采用上报的方式来处理,发生异常处的后续代码不会被执行;
 *                  try语句块中的某一行代码出现异常,该行后面的代码也不会被执行。
 *
 *      深入理解try..catch:
 *          1.catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型。
 *          2.catch可以写多个。建议catch的时候,精准的一个一个处理。这样有利于程序的调试。
 *          3.catch写多个的时候,从上到下,异常类型必须遵守从小到大
 *
 *      在今后的开发中,处理编译时异常,应该是上报还是捕捉呢?
 *          回答:如果希望调用者来处理,就选择throws上报,其他情况选择try..catch捕捉
 *
 *      异常对象有两个非常重要的方法:
 *          1.获取异常对象简单的描述信息:   exception.getMessage();
 *          2.打印异常追踪的堆栈信息:  exception.printStackTrace();
 *
 *      今后我们怎么查看异常的追踪信息,怎么操作才可以快速调试程序?
 *          异常追踪信息需要从上往下查看,忽略SUN公司代码信息(看包名就可以分辨),主要问题出现在自己编写的代码上
 *
 *          例如:
 *              java.io.FileNotFoundException: c:\quan.txt (系统找不到指定的文件。)         (异常原因)
 *                  at java.base/java.io.FileInputStream.open0(Native Method)              SUN公司代码
 *                  at java.base/java.io.FileInputStream.open(FileInputStream.java:212)    SUN公司代码
 *                  at java.base/java.io.FileInputStream.<init>(FileInputStream.java:154)  SUN公司代码
 *                  at java.base/java.io.FileInputStream.<init>(FileInputStream.java:109)  SUN公司代码
 *                  at com.javase.exception.ExceptionText04.m2(ExceptionText04.java:37)    自己编写的代码(最先出异常位置)
 *                  at com.javase.exception.ExceptionText04.m1(ExceptionText04.java:33)    自己编写的代码
 *                  at com.javase.exception.ExceptionText04.main(ExceptionText04.java:25)  自己编写的代码
 *
 *          我们应该首先查看最先出异常的位置,也就是第37行代码。
 *
 */
public class ExceptionText03 {
    public static void main(String[] args) {
        System.out.println("main begin");
        try {
            System.out.println("try begin");
            m1();   // 本行代码如果出现异常,下一行代码不会执行,直接进入catch语句执行
            System.out.println("try over");
        } catch (FileNotFoundException e) {     //该分支是try捕捉到异常之后程序才执行的分支,
                                                // e是引用,其保存的内存地址是后台new出来的异常对象的内存地址。
            e.printStackTrace();    //该行代码的作用是打印异常提示信息
        }
        System.out.println("main over");    //try..catch把异常抓住之后,这行代码会继续执行
    }

    private static void m1() throws FileNotFoundException {     //对m2()方法中有可能出现的异常,采用上报的方式来处理。
        System.out.println("m1 begin");
        m2();
        System.out.println("m1 over");
    }

    private static void m2() throws FileNotFoundException {     //对m3()方法中有可能出现的异常,采用上报的方式来处理。
        System.out.println("m2 begin");
        m3();
        System.out.println("m2 over");
    }

    private static void m3() throws FileNotFoundException { //对有可能发生的异常采用throws上报异常信息
        System.out.println("m3 begin");
//        下行代码报错的原因是源代码 public FileInputStream(String name) throws FileNotFoundException 有异常抛出
//        并且该异常属于编译时异常,在编写代码是需要进行处理的。而m3()在调用该方法的时候如果对异常不处理,这里会报错。
//        解决办法的方式之一是m3()方法继续上抛,也就是在m3()方法后面使用throws 上抛
        new FileInputStream("C:\\temp.txt");//这里出现异常  后台会throw new FileNotFoundException("Invalid file path");
        System.out.println("m3 over");
    }
}
/*
出现异常输出结果:
            main begin
            try begin
            m1 begin
            m2 begin
            m3 begin
            main over
 */
/*
不出现异常输出结果:
            main begin
            try begin
            m1 begin
            m2 begin
            m3 begin
            m3 over
            m2 over
            m1 over
            try over
            main over
 */