异常、try、catch、finally、throw、throws、自定义异常

1. 异常

异常:程序在运行过程中出现的和预想不一致的情况

类和对象:在Java里使用Throwable类表示程序运行过程中出现的不正常现象

Throwable子类:

        Error:程序中出现的错误,程序员不应该尝试解决这种问题,应该让程序终止!

        Exception:程序运行中出现的异常,程序员可以解决这种问题。 异常又分为两种:

                 运行时异常: RuntimeException,可以处理可以不处理

                非运行时异常: 必须要处理,否则编译会报错 (编译时异常)

能出现问题的代码解决思路:

        1、规避:在出现问题之前把出问题的情况排除,不属于异常处理的方式,因为异常还未发生

        规避只能用于运行时异常,不能用在编译时异常

        2、让程序产生异常,再通过异常处理语言来补救

                2.1 try...catch

                2.2 try...catch...finally语句

                2.3 使用 throw和throws抛出异常

public class ExceptionDemo {
    public static void main(String[] args) {
        /*常见的运行时异常 RuntimeException,编译不报错,运行时会出现问题
         ArrayIndexOutOfBoundsException 数组下标越界异常
         StringIndexOutOfBoundsException 字符串下标越界异常
         NullPointerException  空指针异常
         ArithmeticException  算法异常*/

        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入您要选择的编号:");
        int index = scanner.nextInt();
        scanner.close();

        String[] names = {"朦朦", "橘子", "安妮", "崔崔", "芳芳", "巧玲"};

        // 规避的方式让可能出现的异常不出现
        if (index < 0 || index >= names.length) {
            System.out.println("编号不合法");
        } else {
            System.out.println("您选择的是" + names[index]);
        }
    }
}

2. try...catch

try {

         有可能出现异常的代码

}catch(出现的异常类型 e) {

         异常处理语句,通常有两个操作:

                 1. e.printStackTrace(); 打印错误日志,记录在后台给开发人员看

                 2. 给用户一个友好的提示 System.out.println();

}

一个try后面可以有多个catch语句,如果多个异常之间有继承关系,父类的异常处理要放在子类的下面!

如果多个catch里的异常处理语句一样,可以将多个catch语句合并成为一个catch,中间使用 | 连接。这种情况下,异常类型之间不能有继承关系!

public class CatchDemo {
    public static void main(String[] args) {
        int[] nums = {5, 9, 2, 1, 7, 6, 4, 3};
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入一个数字:");
        int i = scanner.nextInt();
        scanner.close();
        String x = "ab";
        Object o = null;
        try {
            System.out.println(1 / i);
            System.out.println(nums[i]);
            char c = x.charAt(i);
            System.out.println(c);
            System.out.println(o.toString());
        } catch (ArithmeticException | ArrayIndexOutOfBoundsException | StringIndexOutOfBoundsException e) {
            e.printStackTrace();
        }

        /*catch (ArithmeticException e) {
            System.out.println("除数不能为0");
            e.printStackTrace();
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组下标越界");
            e.printStackTrace();
        } catch (StringIndexOutOfBoundsException e) {
            System.out.println("字符串下标越界");
            e.printStackTrace();
        } catch (RuntimeException e) {  // 可以catch父类异常
                System.out.println("出现了运行时异常");
                e.printStackTrace();
        }*/
    }
}

3.  throw 和throws

throw和throws关键字的使用:用来抛出异常

假如你是 java.util.Scanner.java 的作者,实现 nextInt()功能,大概的步骤:

         (1) 调用 next()方法获取到用户输入的字符串

         (2) 调用 Integer.parseInt(String s) 方法,将字符串转换成为整数

         (3) 返回这个整数给调用者

throw在方法里用来抛出异常:
        如果throw抛出的是 RuntimeException,方法声明里的throws可以不写

throws用在方法声明里,表示该方法有异常:

        如果方法里抛出的不是RuntimeException,方法声明里必须要使用throws声明异常

        调用这个方法的代码也必须要处理这个异常,要么try...catch,要么抛出去

        如果异常一直向上抛到main方法,main方法会将异常交给JVM虚拟机,虚拟机默认操作就是终止程序,返回状态码 1

throw和throws通常会配合自定义使用!

public class ThrowDemo {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入密码:");  // "hello"
        String password = scanner.next();
        scanner.close();


        // checkPassword(password);
        /*try {
            check(password);
        } catch (Exception e) {
            System.out.println("密码格式错误");
        }*/
        test(password);

        System.out.println("注册成功... ...");
    }

    static void test(String password) throws Exception {
        check(password);
    }

    // 要求密码长度要在[8,15]位,由数字字母组成,不能以数字开头
    static void checkPassword(String password) throws RuntimeException {
        if (password.matches("[a-zA-Z][a-zA-Z0-9]{7,14}")) {
            System.out.println("连接数据库");
            System.out.println("将密码写入到数据库");
        } else {
            throw new RuntimeException("密码不合法!");  // 抛出一个运行异常
        }
    }

    static void check(String password) throws Exception {
        if (password.matches("[a-zA-Z][a-zA-Z0-9]{7,14}")) {
            System.out.println("连接数据库");
            System.out.println("将密码写入到数据库");
        } else {
            throw new Exception("密码格式不合法");
        }
    }
}

4. 自定义异常

自定义异常的使用

throw后面的对象,必须要继承自 Throwable类,通常情况下不直接继承 Throwable

因为Throwable类有两个子类 Exception 和 Error,Error是不能处理的错误

所以自定义异常通常继承自Exception(编译时异常)或者 RuntimeException(运行时异常)

如果继承自Exception,方法声明里必须要使用throws声明抛出

如果继承自RuntionException,方法声明里可以不适用throws声明抛出

package com.atguigu.exception;

public class 数字格式化异常 extends RuntimeException {
}
public class ExceptionDemo {
    public static void main(String[] args) {
        int x = checkNumber("goof");
        System.out.println(x);
    }

    // 判断用户输入的字符串是否是一个合法的数字
    static int checkNumber(String s) {
        try {
            return Integer.parseInt(s);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            throw new 数字格式化异常();
        }
    }
}
public class PasswordFormatException extends Exception {
    public PasswordFormatException(String message) {
        super(message);
    }

    public PasswordFormatException(int min, int max) {
        super("密码由" + min + "到" + max + "位的数字和字母组成,不能以数字开头");
    }
}
public class MyExceptionDemo {
    public static void main(String[] args) {
        String s = "abc";
        try {
            checkPassword(s);
        } catch (PasswordFormatException e) {
            e.printStackTrace();
        }
    }

    static void checkPassword(String password) throws PasswordFormatException {
        int x = 9, y = 18;
        if (password.matches("[a-zA-Z][0-9a-zA-Z]{" + (x - 1) + "," + (y - 1) + "}")) {
            System.out.println("密码格式正确");
        } else {
            // throw new PasswordFormatException("密码由8到16位的数字和字母组成,不能以数字开头");
            throw new PasswordFormatException(x, y);
        }
    }
}

5. 继承里异常的注意事项

子类不能抛出比父类更多(大)的异常

1. 父类如果没有抛出异常,子类不能抛出编译时异常(运行时异常除外)

2. 子类抛出的异常可以是父类抛出的异常的子类。

        在这种情况下,子类如果使用 super.方法名() 调用父类的方法,会报错

        因为子类没有解决父类里的异常

3. 子类不能抛出比父类范围更大的异常,子类在重写方法时

         如果有范围更大的异常,只能使用try...catch解决,不能再抛出

public class ExceptionInheritanceDemo {
}

class XXX {
    @Override
    public String toString() /*throws UnsupportedEncodingException*/ {
        try {
            "hello".getBytes("UTF8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return super.toString();
    }
}

class Base {
    public void test() {
    }
}

class Father extends Base {
    public void test() {
    }

    public void demo() throws IOException {
    }

    public void foo() throws FileNotFoundException {
    }
}

class Son extends Father {
    @Override
    public void test() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            formatter.parse("2020-07-10 14:00:23");
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void demo() throws FileNotFoundException {
    }

    @Override
    public void foo() throws FileNotFoundException {

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值