Java异常处理

Java中的一切不正常的行为,都属于异常(Exception)或错误(Error)。不管是Exception还是Error,都是一个类,都继承于Throwable这个类。

Error类

Error是指JVM虚拟机中无法解决的严重问题,一般造成Error的原因都是设计程序的逻辑出现了问题,比如StackOverflowError(栈溢出),就是典型的逻辑设计出现了问题。这种时候只能放弃这种逻辑。

Exception类

异常一般不需要更换设计思路,可以通过代码来处理这些异常。异常一般发生在某个小范围区域,因此只需要“对症下药”。

异常分为编译时异常(受查异常)和运行时异常(非受查异常)。

编译时异常,就是在编译阶段可以发现的异常,如果发生了编译时异常,那么编译将不能通过,只有先处理好这个异常后才能编译通过。也就是说,当你写好代码后,代码的下方会直接标出红色波浪线提醒你处理异常。比较常见的异常有IOException、FileNotFoundException、ClassNotFoundException、CloneNotSupportedException等

运行时异常在编译阶段不会发现,只有真正的运行之后,才会检测出相应的异常并停止。

运行时异常(RuntimeException)中比较常见的有:ArithmeticException(算数异常)、ArrayIndexOutOfBoundsException(数组越界异常)、NullPoninterException(空指针异常)等。

异常处理

异常的处理一般有两种方式,要么每一行代码的实现都进行一次判断,满足条件后程序才能继续执行;要么利用Java中的关键字trycatchfinallythrowthrows将正常的部分和错误的部分分开,正常的部分正常执行,出现异常的部分,在程序结束后抛出异常。

显然第一种方式不太好用,一旦出现异常,整个程序都不能运行,因此在实际过程中通常采用第二种方式处理异常。

异常的抛出和捕获

要得到异常的信息,就需要抛出异常捕获异常。抛出异常需要用到throw关键字。具体语法为:

throw new XXXExpection("异常产生的原因");//XXXException为某个异常类

一般配合if等条件语句使用,例如:

int[] array = null;
        if (array == null) {
            throw new NullPointerException();
        }

当然,只是抛出异常是不够的,有抛出就要有捕获,捕获异常后才能告知使用者异常的信息。捕获异常需要用到trycatchfinally关键字,具体用法:

try {
    //需要检查的代码
    //一旦捕获到某个异常,无论try中的代码有没有执行完,都将停止执行,并跳到finally部分
}catch(异常类 对象名) {
    对象名.printStackTrace();
}catch(不同的异常类 对象名) {
    对象名.printStackTrace();
}finally {
    //无论是否出现异常,该部分都会执行
}

如果try内部的代码存在的异常没有在捕获的范围内,可以在finally前加上Exception类以确保可以捕获到所有的异常:

catch(Exception e) {
    e.printStackTrace();
}

如果没有写捕获所有的异常类,同时又存在捕获范围外的异常,那么异常处理会交给JVM处理,交给JVM处理虽然也能获得异常信息,但是程序会强行中止。

当我们要处理的异常造成的影响或后果比较严重时,这时就需要强行终止程序或者使程序崩溃;而如果这个异常造成的影响或后果较小或者只是小范围内有影响,就考虑使用try、catch等关键字来处理。

当方法中抛出编译时异常,如果不想处理该异常,此时就可以借助throws将异常抛给方法的调用者来处理,用法:

修饰限定符 返回值类型 方法名(参数列表) throws 异常类型1,异常类型2……

throws的作用仅仅是声明,它不会处理异常,仅提醒方法的调用者处理异常。声明的异常如果存在父子类关系,可以只声明父类。但这种情况下使用catch捕获异常只能先捕获子类异常再捕获父类异常,否则发生语法错误。

自定义异常类

实际开发过程中,Java内置的异常类往往不能满足实际的需求,比如说要设计一个登录器,需要捕获用户名或密码错误异常,显然Java内置的异常类并不能满足需求,那么就需要定义一个用户名错误异常类和密码错误异常类:

public class UsernamesException extends RuntimeException{
    //很明显UsernamesException属于受查异常,
    //因此需要继承于RuntimeException类,使它变为一个异常类
    public UsernamesException() {
    }
    public UsernamesException(String message) {
        super(message);
    }
}
//密码错误异常类同理

自定义异常类的抛出和捕获方法与Java自带异常类别无二致。

实现一个登录功能:

public class User {
    private String username = "zhangsan";
    private String password = "123456789";

    public void login(String username, String password) {
        if (!this.username.equals(username)) {
            throw new UsernamesException("用户名错误或用户名不存在!");
        }
        if (!this.password.equals(password)) {
            throw new PasswordsException("密码错误!");
        }
    }
    public static void main(String[] args) throws UsernamesException, PasswordsException{
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            User user = new User();
            String setUsername = scanner.nextLine();
            String setPassword = scanner.nextLine();
            try {
                user.login(setUsername, setPassword);
                System.out.println("登陆成功!");
            }catch(UsernamesException | PasswordsException e) {
                e.printStackTrace();
            }finally {
                System.out.println("关闭无用资源……");
            }
        }
    }
}

注:如果自定义异常类继承Exception类,则默认属于编译时异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值