Java高级-异常

概念

     在程序运行过程中出现的例外情况,在Java中,异常是一种比较重要的消息机制。

异常类

异常的体系结构

     Throwable是所有异常类的共同父类;Error是所有错误的父类;Exception是所有编译时异常类的父类;

      Exception有两个分支,一个是运行时异常RuntimeException,如NullPointerException 、 ClassCastException;;另一个是检查异常,如 I/O 错误导致的 IOException、SQLException。

Throwable

       所有异常类都是直接或者间接继承Throwable,Throwable类源码如下:

public class Throwable implements Serializable {
    //......
}

       其主要方法如下:

public String getMessage()返回关于发送的异常的详细消息。这个消息在Throwable 类的构造函数中初始化了。
public Throwable getCause()返回一个Throwable对象代表异常原因。
public String toString()使用getMessage()的结果返回类的串级名字。
public void printStackTrace()打印toString()结果和栈层次到System.err,即错误输出流。
public StackTraceElement [] getStackTrace()返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。
public Throwable fillInStackTrace()用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。

Error

        Error表示错误,对于所有的编译时期的错误以及系统错误都是通过Error抛出的。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。在 Java中,错误通过Error的子类描述。

Exception

     Exception表示异常,与Error的区别在于:异常能被程序本身可以处理,错误是无法处理

    Exception的源码如下所示:

public class Exception extends Throwable {
    static final long serialVersionUID = -3387516993124229948L;

    public Exception() {
        super();
    }
    public Exception(String message) {
        super(message);
    }
    public Exception(String message, Throwable cause) {
        super(message, cause);
    }
    public Exception(Throwable cause) {
        super(cause);
    }
    protected Exception(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

RuntimeException

       RuntimeException表示运行时异常,是那些可能在在 Java 虚拟机正常运行期间抛出的异常的超类。如果出现 RuntimeException,那么一定是程序员的错误。      

       源码如下:

public class RuntimeException extends Exception {
    static final long serialVersionUID = -7034897190745766939L;

    public RuntimeException() {
        super();
    }
    public RuntimeException(String message) {
        super(message);
    }
    public RuntimeException(String message, Throwable cause) {
        super(message, cause);
    }
    public RuntimeException(Throwable cause) {
        super(cause);
    }
    protected RuntimeException(String message, Throwable cause,
                               boolean enableSuppression,
                               boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

 

异常处理机制

     在Java中,异常处理机制为:捕获异常和抛出异常。

捕获异常

try-catch语句块用于捕获和处理程序代码抛出的异常

try{
    //可能出现异常的代码,当某个代码语句块出现异常后,其后面的代码语句块不会执行。
}catch (异常类型名 引用名){
    //异常处理的代码
}

        当代码块出现异常后,会执行throw new 异常类型名();然后catch语句会捕捉:异常类型名 引用名 = new 异常类型名();

多重捕获块

       catch语句块可以出现多次

try{
    //可能出现异常的代码,当某个代码语句块出现异常后,其后面的代码语句块不会执行。
}catch (异常类型名 引用名){
    //异常处理的代码
}catch (异常类型名 引用名){
    //异常处理的代码
}......

finally关键字

        正常情况下, 无论程序是否发生异常,finally语句都会执行。因此,在finally语句块里面放置释放资源的语句(例如:关闭数据库连接对象)。

  • 注意事项
1.调用System.exit(0);使JVM停止,finally语句因此不会执行。

2.调用return则不会影响finally语句执行。如下:会输出finally

    try{

          return;

    }finally{

        System.out.println("finally");

   }

  • 使用
try{
    //可能出现异常的代码,当某个代码语句块出现异常后,其后面的代码语句块不会执行。
}catch (异常类型名 引用名){
    //异常处理的代码
}finally{
    //
}

总结

      try语句块必须要出现,catch和finally两者必须出现其一或者同时出现,否则报错能够处理的异常尽量处理,处理不了的异常再抛出去。

抛出异常

throw关键字

     throw用于抛出一个异常。如下所示:

public void deposit(double amount) throws RemoteException{
    //......
    throw new RemoteException();
}

throws关键字

     从方法中抛出的任何异常都必须使用throws。一个方法可以声明抛出多个异常,多个异常之间使用逗号分隔开。如下所示:

public void withdraw(double amount) throws RemoteException, IOException{
    //......
}

异常分类

      Exception 这种异常分两大类运行时异常和编译时异常(非运行时异常)。

1.编译时异常(非运行时异常)

       Exception类和Exception的子类且除了RuntimeException类及其子类的异常都是编译时异常。

       编译时异常要求程序在编译期间必须要对其进行处理,若不处理则要声明抛出的异常类型(在方法上使用throws关键字声明异常类型)。 

2.运行时异常 

       RuntimeException类和RuntimeException的子类都是都是运行时异常。

       运行时异常在程序编译期间可以处理也可以不处理。如果不处理则不用通过throws关键字声明抛出的异常类型。

3.编译时异常和运行时异常的区分

编译时不是程序的Bug,而是为了让程序健壮和稳定;运行时异常是程序的Bug。

4.常见异常

ArithmeticException当出现异常的运算条件时抛出此异常。如被除数为0
ArrayIndexOutOfBoundsException用非法索引访问数组时抛出的异常(索引为负数或者大于等于数组的大小时)。
ClassCastException当试图将对象强制转换为不是实例的子类时,抛出该异常(类型转换异常)。
IllegalArgumentException抛出的异常表明向方法传递了一个不合法或不正确的参数。
IndexOutOfBoundsException指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
NullPointerException当应用程序试图在需要对象的地方使用 null 时,抛出该异常。
NumberFormatException当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
StringIndexOutOfBoundsException此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。
ClassNotFoundException应用程序试图加载类时,找不到相应的类,抛出该异常。
CloneNotSupportedException当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。
IOException操作输入流和输出流时可能出现的异常。
FileNotFoundException 文件未找到异常
NoSuchFieldException 字段未找到异常
NoSuchMethodException 方法未找到抛出的异常
NumberFormatException 字符串转换为数字抛出的异常

 

自定义异常类

自定义编译时异常

       编写一个类继承Exception或Exception的子类(除了RuntimeException及其子类),通常直接继承Exception即可。

自定义运行时异常

      编写一个类继承RuntimeException或RuntimeException的子类,通常直接继承RuntimeException。

示例

       下面以一个用户登录案例演示自定义运行时异常。

     用户名不存在异常类:

/**
 * 自定义用户账户不存在运行时异常
 * @author luckyliuqs
 */
public class UserNotExistException extends RuntimeException {
    private static final long serialVersionUID = 1L;
	
    public UserNotExistException() {}
    public UserNotExistException(String message) {
        super(message);
    }
}

      用户名或密码错误异常类:

/**
 * 自定义用户名或密码错误运行时异常
 * @author luckyliuqs
 */
public class UserNameOrPasswordErrorException extends RuntimeException {
    private static final long serialVersionUID = 2L;
	
    public UserNameOrPasswordErrorException() {}	
    public UserNameOrPasswordErrorException(String message) {
        super(message);
    }
}

       测试类:

public class UserLoginDemo {
    private static Map<String, User> userMap = new HashMap<String, User>();
	
    public static void main(String[] args) {
        userMap.put("Jack", new User("Jack", "12346"));
        try {
            User user = login("Jacks", "123456");
            System.out.println("登录成功!");
        } catch (UserNotExistException e) {   //捕获异常
            System.out.println("登录失败,原因:" + e.getMessage());
        } catch (UserNameOrPasswordErrorException e) {  //捕获异常
            System.out.println("登录失败,原因:" + e.getMessage());
        }
    }
	
    public static User login(String username, String password) {
        User user = userMap.get(username);
        if (user == null) {
            throw new UserNotExistException("用户不存在");  //抛出异常
        }
        if (!password.equals(user.getPassword())) {
            throw new UserNameOrPasswordErrorException("用户名或密码错误"); //抛出异常
        }
        return user;
    }
}

 

 

参考:

https://www.runoob.com

https://blog.csdn.net/hguisu/article/details/6155636

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luckyliuqs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值