16.Java异常

16.Java异常
转载请保留原文链接: http://dashidan.com/article/java/basic/16.html

Java异常是Java提供的一种识别及响应错误的一致性机制.

① Java异常机制相关关键字

Java异常机制相关关键字有: trycatchfinallythrowthrows.
关键字解释:

  • try 用于监听. 将被监听的代码(可能抛出异常的代码)放在try语句块之内, 当try语句块内发生异常时,异常就被抛出.
  • catch 用来捕获try语句块中发生的异常.
  • finally finally语句块总是会被执行. 主要用于回收在try块里打开的物理资源(如文件, 网络连接, 数据库连接等).

finally语句中return

只有finally块执行完成之后,才会执行try或者catch块中的return或者throw语句. 如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止.

  • throw 用于抛出异常.
  • throws 用在方法签名中,用于声明该方法可能抛出的异常.

② Java异常框架

Java将可抛出(Throwable)的结构分为三种类型:

  • 编译异常(Checked Exception)
  • 运行时异常(RuntimeException)
  • 错误(Error)

Java异常框架继承关系如图:
图15-1

1.Throwable

ThrowableJava语言中所有错误或异常的超类, 包含两个子类:ErrorException.它们通常用于指示发生了异常情况.Throwable包含了其线程创建时线程执行堆栈的快照,提供了printStackTrace()等接口用于获取堆栈跟踪数据等信息.

2.运行时异常RuntimeException

RuntimeException是那些可能在Java虚拟机正常运行期间抛出的异常的超类, 简称运行时异常. RuntimeException及其子类都被称为运行时异常.

Java编译器不会检查运行时异常.当程序中可能出现这类异常时,倘若既”没有通过throws声明抛出它”,也”没有用try-catch语句捕获它”,还是会编译通过.

虽然Java编译器不会检查运行时异常, 但是我们也可以通过throws进行声明抛出, 也可以通过try-catch对它进行捕获处理. 如果产生运行时异常,则需要通过修改代码来进行避免.

例如:
* 除数为零时产生的ArithmeticException异常
* 数组越界时产生的IndexOutOfBoundsException异常
* fail-fail机制产生的ConcurrentModificationException异常等,都属于运行时异常.

部分常用运行时异常说明
异常描述
ArithmeticException除数为零异常
ArrayIndexOutOfBoundsException数组越界
ClassCastException对象转型错误
IllegalArgumentException参数不合法
IndexOutOfBoundsException指示某排序索引(例如对数组、字符串或向量的排序)超出范围
NegativeArraySizeException数组长度为负值
NullPointerException空指针异常
NumberFormatException当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常.

3.编译异常Exception

Exception类以及Exception的子类中除了”运行时异常”之外的其它子类都属于被检查异常. 此类异常,要么通过throws进行声明抛出,要么通过try-catch进行捕获处理,否则不能通过编译.

部分常用编译异常说明
异常描述
ClassNotFoundException应用程序试图加载类时,找不到相应的类,抛出该异常.
FileNotFoundException文件不存在异常
ClassCastException对象转型错误
InterruptedException一个线程被另一个线程中断,抛出该异常.
NoSuchFieldException请求的变量不存在
NoSuchMethodException请求的方法不存在

4.Error

Error类及其子类统称错误. 用于指示试图捕获的严重问题, 大多数这样的错误都是异常条件. 和运行时异常一样, 编译器也不会检查Error. 当资源不足、约束失败、或是其它导致程序无法继续运行的条件发生时, 就产生错误. 程序本身无法修复这些错误.

例:

  • VirtualMachineError就属于错误.

  • 按照Java惯例, 不应该实现任何新的Error子类, 需要自定义异常可以采用Exception类.

到底该哪一种异常?

对于可以恢复的条件使用被检查异常,对于程序错误使用运行时异常.虚拟机及系统错误采用Error.

③ 捕获异常

使用trycatch关键字可以捕获异常.try/catch代码块放在异常可能发生的地方.

语法如下:

try {
    /** 程序代码*/
} catch (Exception e) {
    /** 异常处理*/
}
一个`try`代码块后面跟随多个`catch`代码块的情况就叫多重捕获. 可以在 try 语句后面添加任意数量的 catch 块. 如果保护代码中发生异常,异常被抛给第一个 catch 块. 如果抛出异常的数据类型与捕获异常类型匹配, 就会被捕获. 如果不匹配,它会被传递给下一个`catch`块.直到异常被捕获或者通过所有的`catch`块. 语法如下:
try {
    /** 程序代码*/
} catch (Exception1 e) {
    /** 异常处理*/
} catch (Exception1 e) {
    /** 异常处理*/
}

④ 抛出异常

可以使用throw关键字抛出一个异常.

public static void testThrow() {
    /** 方法体*/
    throw new NullPointerException();
}
如果一个方法没有捕获一个`编译异常`, 那么该方法必须使用`throws`关键字来声明. `throws`关键字放在方法签名的尾部. 示例代码:
public static void testThrows() throws NullPointerException {
    /** 方法体*/
}
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开. 例如,下面的方法声明抛出`NullPointerException`和`ArithmeticException` 示例代码:
public static void testThrows() throws NullPointerException, ArithmeticException {
    /** 方法体*/
}

⑤ finally关键字

finally关键字用来创建在try代码块后面执行的代码块. 无论是否发生异常,finally代码块中的代码总会被执行. 在finally代码块中,可以运关闭链接, 释放系统资源等必须要执行的语句.

finally代码块出现在catch代码块最后.

语法如下:

try {
    /** 方法体*/
} catch (Exception e) {
    /** 异常处理*/
} finally {
    /** finally语句*/
}

finally 块并非强制添加.

try 代码后不能既没 catch 块也没 finally 块.

示例代码:

package com.dashidan.lesson15;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 15.Java异常
 * 测试finally return
 */
public class Demo2 {
    public static void main(String[] args) {
        int result = testFinallyReturn();
        System.out.println("result: " + result);
    }

    public static int testFinallyReturn() {
        int a;
        try {
            a = 1;
            /** 抛出异常*/
            System.out.println("抛出异常");
            throw new NullPointerException();
        } catch (NullPointerException e) {
            a = 2;
            /** 捕获异常*/
            System.out.println("捕获异常");
            e.printStackTrace();
            /** 注意这里没有返回*/
            System.out.println("注意这里没有返回");
            return a;
        } finally {
            a = 3;
            System.out.println("finally执行返回");
            /** 抛出异常后, 执行finally的语句, 如果这里返回,不再执行catch中语句*/
            return a;
        }
    }
}

输出:

    抛出异常
    捕获异常
    注意这里没有返回
    finally执行返回
    result: 3
    java.lang.NullPointerException
        at com.dashidan.lesson15.Demo2.testFinallyReturn(Demo2.java:21)
        at com.dashidan.lesson15.Demo2.main(Demo2.java:11)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

⑥ 自定义异常

Java中自定义异常需要注意:

  • 所有异常都必须是 Throwable 的子类.
  • 如果想写一个检查性异常类,则需要继承 Exception 类.
  • 如果想写一个运行时异常类,那么需要继承 RuntimeException 类.
package com.dashidan.lesson15;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 15.Java异常
 * 自定义异常
 */
public class SelfException extends Exception {
}

示例代码:

package com.dashidan.lesson15;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 15.Java异常
 */
public class Demo1 {
    public static void main(String[] args) {
        try {
            /** 方法体*/
            testThrow();
            testThrows();
        } catch (NullPointerException e) {
            /** 异常处理*/
            System.out.println("run catch NullPointerException.");
            e.printStackTrace();
        } catch (Exception e) {
            /** 异常处理*/
            System.out.println("run catch Exception.");
            e.printStackTrace();
        } finally {
            /** finally语句*/
            System.out.println("run finally.");
        }
    }

    public static void testThrow() {
        /** 方法体*/
        throw new NullPointerException();
    }

    public static void testThrows() throws NullPointerException, ArithmeticException {
        /** 方法体*/
    }
}

输出:

    java.lang.NullPointerException
    at com.dashidan.lesson15.Demo1.testThrow(Demo1.java:30)
    at com.dashidan.lesson15.Demo1.main(Demo1.java:12)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
    run catch NullPointerException.
    run finally.

⑦ 相关文章

JJava从入门到精通

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值