香雨站

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 94|回复: 0

JAVA 异常处理

[复制链接]

1

主题

3

帖子

3

积分

新手上路

Rank: 1

积分
3
发表于 2022-12-2 19:02:29 | 显示全部楼层 |阅读模式
一、 传统处理异常的方式

public class Test01 {
        public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入第一个数:");
               
                int num1 = 0;
                if(sc.hasNextInt()) {                       
                        num1 = sc.nextInt();
                       
                        System.out.println("请输入第二个数:");
                        int num2 = 0;
                        if(sc.hasNextInt()) {
                                num2 = sc.nextInt();
                               
                                if(0 == num2) {
                                        System.out.println("除数不能为0!");
                                }else {                                       
                                        int r = num1 / num2;
                                        System.out.println("num1/num2 = "+r);
                                }

                        }else {
                                System.out.println("第二个数输入不是数字");
                        }
                       
                }else {
                        System.out.println("第一个数输入不是数字!");
                }
        }
}缺点:
1.通过判断会影响程序执行效率;
2.判断逻辑和业务逻辑交织在一起,可维护性很差。
二、异常

异常是指在程序的运行过程中所发生的不正常的情况,它会中断正在运行的程序。
1.异常处理机制
java中通过异常处理机制为程序员提供异常处理的能力,保持程序继续运行而不中断。


2.异常处理
涉及异常处理的关键字有 try...catch/try...catch...finally
2.1 try/catch
把有可能产生异常的代码放到 try 代码块中,catch 代码块负责捕获并处理异常。
1.正常执行,没出现任何异常


2.出现异常,异常处理,正常结束


Exception 是所有异常类的直接或者间接父类。
异常常见方法
printStackTrace:打印异常的执行堆栈信息
java.util.InputMismatchException
        at java.util.Scanner.throwFor(Scanner.java:864)
        at java.util.Scanner.next(Scanner.java:1485)
        at java.util.Scanner.nextInt(Scanner.java:2117)
        at java.util.Scanner.nextInt(Scanner.java:2076)
        at cn.sxt02.exception02.Test01.main(Test01.java:14)一般而言,异常堆栈信息很多,开发者只需第一行和最后一行即可
第一行:异常简单信息(异常类型,异常的描述等);
最后一行:异常出现的位置(类>方法>方法的具体行位置);
注意:在控制台中异常堆栈信息输出位置不固定,但第一行和最后一行位置固定。
getMassage:返回异常的描述信息
package cn.sxt02.exception02;
import java.util.Scanner;
public class Test01 {
        public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入第一个数:");

                int num1 = 0;
                int num2 = 0;
               
                try {
                        num1 = sc.nextInt();

                        System.out.println("请输入第二个数:");
                        num2 = sc.nextInt();

                        int r = num1 / num2;
                        System.out.println("num1/num2 = " + r);
                }catch (Exception e) {
                        System.out.println("程序出现异常");
                        // 打印异常的信息
                        // System.out.println(e.toString());
                       
                       
                        // 打印异常堆栈信息
                         e.printStackTrace();
                       
                        // 返回异常的描述信息,如果没有信息,返回null(InputMismatchException 没有描述信息)
                        System.out.println(e.getMessage());
                }
               
                System.out.println("程序正常结束");
        }
}3.异常类型不匹配


4.多重catch
public class Test03 {
        public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入第一个数:");

                int num1 = 0;
                int num2 = 0;
               
                try {
                        num1 = sc.nextInt();

                        System.out.println("请输入第二个数:");
                        num2 = sc.nextInt();

                        int r = num1 / num2;
                        System.out.println("num1/num2 = " + r);
                }catch (ArithmeticException e) {
                        System.out.println("数学计算异常:"+e.getMessage());
                }catch(InputMismatchException e) {
                        System.out.println("输入不匹配异常:"+e.getMessage());
                }catch (Exception e) {
                        System.out.println("发送异常:"+e.getMessage());
                }
               
                System.out.println("程序正常结束");
        }
}2.2 try/catch/finally
把有可能产生异常的代码放到try中,catch 负责匹配并处理异常,finally 块用于进行收尾工作(关闭数据库、关闭文件、释放内存等资源)
不管是否发生异常,finally 都执行。
public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入第一个数:");

                int num1 = 0;
                int num2 = 0;

                try {
                        num1 = sc.nextInt();

                        System.out.println("请输入第二个数:");
                        num2 = sc.nextInt();

                        int r = num1 / num2;
                        System.out.println("num1/num2 = " + r);
                } catch (Exception e) {
                        System.out.println("程序出现异常");
                } finally {
                        System.out.println("不管是否出现异常,finally都执行");
                }

                System.out.println("程序正常结束");
        }finally 总是执行,常用来进行收尾类的工作。
finally不执行的情况:System.exit(0)正常退出jvm,finaly不会执行。
catch 可以省略,变成 try...finally 块。
2.3 return
存在return的try/catch/finally 执行顺序
package cn.sxt02.exception03;

/**
* 存在return的情况
*/
public class Test02 {

        public static int div(int a, int b) {

                try {
                        int r = a / b;
                        return r;

                } catch (Exception e) {
                        System.out.println("出现异常");

                        return 0;

                } finally {
                        System.out.println("我是finally");
                }

        }

        public static void main(String[] args) {

                int r = Test02.div(10, 0);
                System.out.println("r=" + r);
                System.out.println("程序正常结束");
        }
}3.异常的分类


Throwable 类是Java 语言中所有错误(Error)或异常(Exception)的父类,只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者Java throw 语句抛出。
Error 类表示错误类。仅靠程序本身无法恢复的严重错误。jvm 内存耗尽、jvm 崩溃等。
Exception 类表示异常类,可以通过java异常处理机制处理。
Exception 根据是否处理分为两种情况。
1.RuntimeException:运行时异常。不要求程序必须做出处理。是所有运行时异常的父类。
2.CheckedException:检查时异常。要求程序必须处理,不处理编译不通过。
public class Test01 {
        public static void main(String[] args) {
                // 运行时异常
                Scanner sc = new Scanner(System.in);
                // runtime exception
                int r = sc.nextInt();
                System.out.println("r = "+ r);
               
                // 检查时异常
                SimpleDateFormat df = new SimpleDateFormat();
                try {
                        Date date = df.parse("2019");
                } catch (ParseException e) {
                        e.printStackTrace();
                }
        }
}常见的运行时异常
ArithmeticException:数学计算异常。比如除数为0
InputMismatchException:输入不匹配异常
ArrayIndexOutofBoundsException:数组下标越界异常。
NullPointException:空指针异常,对象没有初始化就使用时,jvm会抛出该异常
IllegalArgumentException:非法参数异常。
ClassCastException:强制类型转换异常。
NumberFormatException:数字格式化异常。比如把“abc”格式化成数字。

常见的检查时异常:
ClassNotFoundException:类没有被发现异常。
SQLException:数据库相关异常
IOException:IO操作异常
ParseException:解析错误异常
FileNotFoundException:文件未发现异常。
运行时异常和检查时异常的区别
运行时异常:包括RuntimeException及其所有子类。不要求程序必须对它们作出处理,比如InputMismatchException、ArithmeticException、NullPointerException等。即使没有使用try-catch或throws进行处理,仍旧可以进行编译和运行。如果运行时发生异常,会输出异常的堆栈信息并中止程序执行。
Checked异常(非运行时异常):除了运行时异常外的其他异常类都是Checked异常。程序必须捕获或者声明抛出这种异常,否则出现编译错误,无法通过编译。处理方式包括两种:通过try-catch捕获异常,通过throws声明抛出异常从而交给上一级调用方法处理。
三、声明异常

1.throws 关键字
当一个方法可能存在异常,而此时自身又无法更好的处理,可以交给外界处理。此时用throws 声明并抛出异常。
public class Test01 {

        public static int div(int a, int b) throws ArithmeticException{
                int r = 0;
                r = a / b;
                return r;
        }

        public static void main(String[] args) {
                try {
                        Test01.div(10, 0);
                } catch (ArithmeticException e) {
                        System.out.println("除数不能为0");
                }
        }
}开发者可以根据需要声明检查时异常(Exception 或者非运行时异常)和运行时异常(RuntimeException 或其子类)。
如果调用处也不知道如何处理异常,可选择继续声明异常,我们把这个过程称为异常上抛。
public class Test01 {

        public static int div(int a, int b) throws Exception{
                int r = 0;
                r = a / b;
                return r;
        }

        public static void main(String[] args) throws Exception{
               
                //【1】 调用处知道如何处理!
                /*
                try {
                        Test01.div(10, 0);
                } catch (Exception e) {
                        e.printStackTrace();
                }
                */
               
                // 【2】调用处也不知道如何处理
                Test01.div(10, 0);
               
        }
}2.声明异常和重载的关系
声明异常和重载没有任何关系
public class Test01 {

        public static int div(int a, int b) throws Exception{
                int r = 0;
                r = a / b;
                return r;
        }
       
        public static int div(int a, int b) {
                int r = 0;
                r = a / b;
                return r;
        }
}方法重载
1.方法名相同;
2.参数列表不同(个数、类型、顺序);
3.和返回值、修饰符、声明异常无关。
3.声明异常和重写的关系
声明异常和方法重写有关系。
1.父类方法声明了异常(检测时或者运行时),子类可以不声明任何异常。
public class Father {

        public void showInfo() throws Exception{
               
        }
}
public class Son extends Father{
       
        @Override
        public void showInfo(){
               
        }
       
}可以认为:父类抛出异常,子类在重写过程中把该异常处理掉了,所以子类方法不一声明异常。
2.父类方法声明没有声明任何异常(检测时或者运行时),子类也不声明异常或者声明运行时异常。
public class Father {

        public void showInfo(){
               
        }
}
public class Son extends Father{
       
        @Override
        public void showInfo() throws Exception{
               
        }
       
}3.父类声明了异常(检测时或者运行时),子类声明完全一样的异常。
public class Father {

        public void showInfo() throws Exception{
               
        }
}
public class Son extends Father{
       
        @Override
        public void showInfo() throws Exception {
               
        }
       
}四、手动抛出异常

1.throw
除了系统自动抛出异常外,有些问题需要开发者手动抛出异常。使用关键字throw。
package cn.sxt02.exception06;

public class Student {
        private String name;
        private String gender;

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        public String getGender() {
                return gender;
        }

        public void setGender(String gender) throws Exception{
                if(gender.equals("男") || gender.equals("女")) {                       
                        this.gender = gender;
                }else {
                        throw new Exception("性别不合法!");
                }
        }

        public Student(String name, String gender) {
                super();
                this.name = name;
                this.gender = gender;
        }

        public Student() {
                super();
        }
       
}
public class Test01 {
        public static void main(String[] args){
                Student stu = new Student();
                stu.setName("二狗");
                try {
                        stu.setGender("xxx");
                } catch (Exception e) {
                        System.out.println(e.getMessage());
                }
        }
}2.自定义异常
如果开发者需要手动抛出的异常在系统里面并不存在,可以自定义异常。
如果要自定义异常,首先要确定异常类型,如果异常是运行时异常,必须继承RuntimeException或其子类;如果异常是检查时异常,必须继承Exception 或其子类。
异常的命名方式,参考系统命名方式,以Exception 结尾。
public class AgeException extends Exception{

        public AgeException() {
                super();
        }

        public AgeException(String message) {
                super(message);
        }
       
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|香雨站

GMT+8, 2025-7-2 13:05 , Processed in 0.102112 second(s), 24 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.. 技术支持 by 巅峰设计

快速回复 返回顶部 返回列表