自学内容网 自学内容网

零基础Java第二十二期:异常(二)

目录

一、异常的捕获

1.1. 多个异常,一次捕获

1.2. 异常之间的父子关系 

1.3. finally 

二、自定义异常 


一、异常的捕获

1.1. 多个异常,一次捕获

        由于Exception类是所有异常类的父类,因此可以用这个类型表示捕捉所有异常。也就是说,编译器会告诉你有风险,但就是不告诉你风险是啥。这种写法呢,我们不推荐

public class Main {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3};
        try {
            System.out.println("before");
            arr = null;
            System.out.println(arr[100]);
            System.out.println("after");
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("after try catch");
    }
}

1.2. 异常之间的父子关系 

      如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则语法错误。来看下面的代码,因为NullPointerExceptions是RuntimeException的子类,在运行的时候,直接会被第一个catch所捕获,第二个异常就相当于没写。

public class Main {
    public static void main(String[] args) {
        try {
            throw new NullPointerException();
        } catch (RuntimeException e) {
            System.out.println("捕获运行时异常");
            e.printStackTrace();
        } catch (NullPointerException e) {
//Exception 'java.lang.NullPointerException' has already been caught
            System.out.println("捕获空指针异常");
        }
    }
}

1.3. finally 

      在写程序时,有些特定的代码,不论程序是否发生异常,都需要执行,比如程序中打开的资源:网络连接、数据库 连接、IO流等,在程序正常或者异常退出时,必须要对资源进进行回收。另外,因为异常会引发程序的跳转,可能 导致有些语句执行不到,finally就是用来解决这个问题的。

      语法规则: 

try{
    //可能发生的异常;
} catch(异常类型 e){
   //对捕获的异常进行处理;
} finally{
   //此处的语句无论是否发生异常,都会被执行到;
}

       我们来用下面的代码来举例

public class Main {
    public static void main(String[] args) {
        try {
            //执行一些逻辑完毕之后,可能释放一些资源;
            //释放资源的操作可能会抛出一些异常,为了避免异常导致程序崩溃,可以使用try-catch
            if (cond1) {
                return;
            }
            if (cond2) {
                throw new Exception("某些未知异常");
            }
            release();
        }
    }

    private static void release() {
    }
}

        如果说资源没有及时释放,那么后期别人使用的时候就会很糟糕。针对这种情况,我们要在第一个if里面也调用一下release,或者抛出异常的时候,我们再后面也加上一个catch来捕获我们抛出的异常。

public class Main {
    public static void main(String[] args) {
        try {
            //执行一些逻辑完毕之后,可能释放一些资源;
            //释放资源的操作可能会抛出一些异常,为了避免异常导致程序崩溃,可以使用try-catch
            if (cond1) {
                release();
                return;
            }
            if (cond2) {
                throw new Exception("某些未知异常");
            }
            release();
        } catch (Exception e){
            release();
        }
    }

    private static void release() {
    }
}

      这样的方法看似可以解决问题,但是代码的可维护性比较低。比如说,我们多个人一起来写代码,一个人写了,其他人不知道需要调用或者加上其他分支。这时候我们就可以用finally解决。按照下面的代码,无论try-catch语句如何执行,都会执行finally。

public class Main {
    public static void main(String[] args) {
        try {
            //执行一些逻辑完毕之后,可能释放一些资源;
            //释放资源的操作可能会抛出一些异常,为了避免异常导致程序崩溃,可以使用try-catch
            //出现异常或者遇到return语句,是资源无法释放
            if (cond1) {
                release();
                return;
            }
            if (cond2) {
                throw new Exception("某些未知异常");
            }
        } catch (Exception e){
        }finally {
            release();
        }
    }

    private static void release() {
    }
}
public class Main {
    public static void main(String[] args) {
        try {
            //执行一些逻辑完毕之后,可能释放一些资源;
            //释放资源的操作可能会抛出一些异常,为了避免异常导致程序崩溃,可以使用try-catch
            //出现异常或者遇到return语句,是资源无法释放
            int a = 1;
            int b = 2;
            if (a < b) {
                throw new NullPointerException("a小于b");
            }
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            release();
        }
    }

    private static void release() {
        System.out.println("release释放资源");
    }
}

     我们来看下面一段代码,老铁们来猜一下运行结果是多少。 

public class Main {
    public static int func(){
        try{
            return 10;
        } catch(Exception e) {
            return 20;
        } finally {
            return 30;
        }
    }
    public static void main(String[] args) {
        System.out.println(func());
    }
}

        我们可以看到结果是30,这是因为执行到try的时候,本来该返回10,但是我们一定需要执行finally语句,返回值30就会把之前的10覆盖。如果我们把try语句里面改成抛出一个异常,那么同理,catch语句的返回值20也会被30覆盖。

二、自定义异常 

        Java 中虽然已经内置了丰富的异常类, 但是并不能完全表示实际开发中所遇到的一些异常,此时就需要维护符合我 们实际情况的异常结构。实际中,经常需要根据业务类型自定义异常。比如我们在进行登陆的时候,用户输错了密码出现的异常或者是网络不好出现的掉线异常。 

        那我们如何自定义异常呢?异常本质是类,我们自己写一个类,让这个类继承Java标准库里面的异常(如Exception、RuntimeException)。下面我们来讲一下登录系统。

       首先我们先来设置登录系统

//设置登录系统
class Login{
    private String username = "crane";
    private String password = "24170";

    public void login(String username,String password){
        if (!username.equals(this.username)) {
            System.out.println("用户名错误!");
            return;
        }
        if(!password.equals(this.password)){
            System.out.println("密码错误!");
        }
        System.out.println("登录成功");
    }
}

     我们再定义异常类。

//创建异常类
class UsernameException extends Exception{

}
class PasswordException extends Exception {

}

下面再对异常进行抛出

    public void login(String username,String password) throws UsernameException,PasswordException{
        if (!username.equals(this.username)) {

            throw new UsernameException();
        }
        if(!password.equals(this.password)){

            throw new PasswordException();
        }
        System.out.println("登录成功");
    }
}

 以下是完整代码:

//创建异常类
class UsernameException extends Exception{

}
class PasswordException extends Exception {

}

//设置登录系统
class Login{
    private String username = "crane";
    private String password = "24170";

    public void login(String username,String password) throws UsernameException,PasswordException{
        if (!username.equals(this.username)) {

            throw new UsernameException();
        }
        if(!password.equals(this.password)){

            throw new PasswordException();
        }
        System.out.println("登录成功");
    }
}

public class Main {
    public static void main(String[] args) {
        Login lg = new Login();
        try {
            lg.login("night", "123456");
        } catch (UsernameException e){
            System.out.println("用户名错误");
        } catch (PasswordException e){
            System.out.println("密码错误");
        }
    }
}

 


原文地址:https://blog.csdn.net/2401_85198927/article/details/143890064

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!