异常(二)

3.1、 try、 catch 和 finally
异常的捕获和处理需要采用 try 和 catch 来处理,具体格式如下:
try {
}catch(OneException e) {
}catch(TwoException e) {
}finally {

try 中包含了可能产生异常的代码
try 后面是 catch, catch 可以有一个或多个, catch 中是需要捕获的异常
当 try 中的代码出现异常时,出现异常下面的代码不会执行,马上会跳转到相应的 catch语句块中,如果没有异常不会跳转到 catch 中。
finally 表示,不管是出现异常,还是没有出现异常, finally 里的代码都执行, finally 和catch 可以分开使用,但 finally 必须和 try 一块使用,如下格式使用 finally 也是正确的。

public class ExceptionTest {
    public static void main(String[] args) {
        int i1 = 100;
        int i2 = 0;
        // try 里是出现异常的代码
        // 不出现异常的代码最好不要放到 try 作用
        try {
            // 当出现被 0 除异常,程序流程会执行到“catch(ArithmeticException ae)”语句
            // 被 0 除表达式以下的语句永远不会执行
            int i3 = i1 / i2;
            // 永远不会执行
            System.out.println(i3);
            // 采用 catch 可以拦截异常
            // ae 代表了一个 ArithmeticException 类型的局部变量
            // 采用 ae 主要是来接收 java 异常体系给我们 new 的 ArithmeticException 对象
            // 采用 ae 可以拿到更详细的异常信息
        } catch (ArithmeticException ae) {
            System.out.println("被 0 除了");
        }
    }
}
3.2、 getMessage 和 printStackTrace()
如何取得异常对象的具体信息,常用的方法主要有两种:

取得异常描述信息: getMessage()
取得异常的堆栈信息(比较适合于程序调试阶段): printStackTrace();
public class ExceptionTest {
    public static void main(String[] args) {
        int i1 = 100;
        int i2 = 0;
        try {
            int i3 = i1 / i2;
            System.out.println(i3);
        } catch (ArithmeticException ae) {
            // ae 是一个引用,它指向了堆中的 ArithmeticException
            // 通过 getMessage 可以得到异常的描述信息
            System.out.println(ae.getMessage());
        }
    }
}

3.3、受控异常

受控异常必须处理,否则无法编译通过!

public class ExceptionTest {
    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("test.txt");
        } catch (FileNotFoundException e) {//此异常为受控异常,必须处理

            e.printStackTrace();
        }
    }
}

3.4、 finally 关键字
finally 在任何情况下都会执行,通常在 finally 里关闭资源
public class ExceptionTest {
    public static void main(String[] args) {
        // 因为 fis 的作用域问题,必须放到 try 语句块外,局部变量必须给初始值
        // 因为是对象赋值为 null
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("E:\\test.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                System.out.println("-------before fis.close--------");
                // 放到 finally 中的语句,程序出现任何问题都会被执行
                // 所以 finally 中一般放置一些需要及时释放的资源
                fis.close();
                System.out.println("-------after fis.close--------");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


深入 finally(1):

public class ExceptionTest {
    public static void main(String[] args) {
        int i1 = 100;
        int i2 = 10;
        try {
            int i3 = i1 / i2;
            System.out.println(i3);
            return;
        } catch (ArithmeticException ae) {
            ae.printStackTrace();
        } finally {
            // 会执行 finally
            System.out.println("----------finally---------");
        }
    }
}

深入 finally(2):

public class ExceptionTest {
    public static void main(String[] args) {
        int i1 = 100;
        int i2 = 10;
        try {
            int i3 = i1 / i2;
            System.out.println(i3);
            // return;
            System.exit(-1); // java 虚拟机退出
        } catch (ArithmeticException ae) {
            ae.printStackTrace();
        } finally {
            // 只有 java 虚拟机退出不会执行 finally
            // 其他任何情况下都会执行 finally
            System.out.println("----------finally---------");
        }
    }
}

深入 finally(3):

public class ExceptionTest {
    public static void main(String[] args) {
        int r = method1();
        // 输出为: 10
        System.out.println(r);
    }

    private static int method1() {
        int a = 10;
        try {
            return a;
        } finally {
            a = 100;
        }
    }
}

 

深入 finally(4):

public class ExceptionTest {
    public static void main(String[] args) {
        int r = method1();
        // 输出为: 100
        System.out.println(r);
    }

    private static int method1() {
        int a = 10;
        try {
            a = 50;
        } finally {
            a = 100;
        }
        return a;
    }
}

3.5、如何声明异常

在方法定义处采用 throws 声明异常, 如果声明的异常为受控异常,那么调用方法必须处理此异常。

(1)、声明受控异常

public class ExceptionTest {
    public static void main(String[] args){
        
        try {
            readFile();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static void readFile() throws FileNotFoundException, IOException { // 声明异常,声明后调用者必须处理
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("test.txt");
        } finally {
            fis.close();
        }
    }
}

(2)、声明非受控异常

public class ExceptionTest {
    public static void main(String[] args) {
        // 不需要使用 try...catch..,因为声明的是非受控异常
         method1();
        // 也可以拦截非受控异常
/*        try {
            method1();
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }*/
    }

    // 可以声明非受控异常
    private static void method1() throws ArithmeticException {
        int i1 = 100;
        int i2 = 0;
        int i3 = i1 / i2;
        System.out.println(i3);
    }
}

3.6、如何手动抛出异常

采用异常来处理参数非法

public class ExceptionTest {
    public static void main(String[] args) {
        try {
            int ret = method1(1000, 10);
            System.out.println(ret);
        } catch (Exception iae) { // 可以采用 Exception 拦截所有的异常
            System.out.println(iae.getMessage());
        }
    }

    private static int method1(int value1, int value2) {
        if (value2 == 0) {
             手动抛出异常
            throw new IllegalArgumentException("除数为 0");
        }
        if (!(value1 > 0 && value1 <= 100)) {
            // 手动抛出异常
            throw new IllegalArgumentException("被除数必须为 1~100 之间的数据");
        }
        int value3 = value1 / value2;
        return value3;
    }
}

throws 和 throw 的区别? throws 是声明异常, throw 是抛出异常

public class ExceptionTest {
    public static void main(String[] args) {
        try {
            int ret = method1(1000, 10);
            System.out.println(ret);
        } catch (Exception iae) {
            System.out.println(iae.getMessage());
        }
    }

    private static int method1(int value1, int value2) {
        try {
            if (value2 == 0) {
                 手动抛出异常
                throw new IllegalArgumentException("除数为 0");
                // 加入如下语句编译出错, throw 相当于 return 语句
                // System.out.println("----------test111-----------");
            }
            if (!(value1 > 0 && value1 <= 100)) {
                // 手动抛出异常
                throw new IllegalArgumentException("被除数必须为 1~100 之间的数据");
            }
            int value3 = value1 / value2;
            return value3;
        } finally {
            // throw 虽然类似 return 语句,但 finally 会执行的
            System.out.println("-----------finally------------");
        }
    }
}

3.7、异常的捕获顺序
异常的捕获顺序应该是:从小到大
public class ExceptionTest {
    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("test.txt");
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        } 
/*        catch (FileNotFoundException e) {
            e.printStackTrace();
        }*/
        // 将 IOException 放到前面,会出现编译问题
        // 因为 IOException 是 FileNotFoundException 的父类,
        // 所以截获了 IOException 异常后, IOException 的子异常
        // 都不会执行到,所以再次截获 FileNotFoundException 没有任何意义
        // 异常的截获一般按照由小到大的顺序,也就是先截获子异常,再截获父异常
    }
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值