Java异常

异常

1.1异常处理结构

  • Java针对异常的处理提供了try、catch、finally、throws、throw五个核心关键字,其中前三个关键字就可以组成常用异常处理结构。语法如下

    public void method(){
    try {
          // 代码段(此处不会产生异常)
    } catch (异常类型 ex) {
          // 对异常进行处理的代码段
    }
    // 代码段
    }
    
    

    捕获异常

  • try——执行可能产生 异常的代码

  • catch——捕获异常

  • finally——无论是否发生异常,代码总能执行

    声明赋值

  • throws——声明方法可能要抛出的各种异常
    抛出异常

  • throw——手动抛出异常

注意:以上格式中的catch语句、finally语句都可选。实际上,这并不是表示catch语句、finally语句可以同时消失。异常格式的常见组合有try-catch、try-catch-finally、try-finally三种。

1.1.1 使用try-catch

import java.util.Scanner;

public class Demo01 {
    public static void main(String[] args) {
        //创建扫描器
        Scanner input=new Scanner (System.in);
        //如果除数或者被除数为0就执行catch
        try {
            System.out.print("请输入果实采摘量(公斤)");
            int weight=input.nextInt();
            System.out.println("请输入果商数(家):");
            int num=input.nextInt();
            //除数和被除数不能为0      如果除数或者被除数为0就执行catch
            System.out.println("每家果商供应"+weight/num+"公斤水果");
            System.out.println("欢迎再来,预祝生意兴隆!");
        } catch (Exception e) {
            System.out.println("出现错误:采摘量和果商数应为整数,果商数应大于零!");
        }
    }
}

以上程序中使用了异常处理语句,当程序出现异常时,异常会被try语句监听到,然后被JVM抛出,被catch语句捕获进行处理,执行catch语句内的异常处理代码

1.1.2 使用try-catch 并且明确的描述异常类型,精确定位问题所在

import java.util.Scanner;

public class Demo01 {
    public static void main(String[] args) {
        Scanner input=new Scanner (System.in);
        try {
            System.out.print("请输入果实采摘量(公斤)");
            int weight=input.nextInt();
            System.out.println("请输入果商数(家):");
            int num=input.nextInt();
            System.out.println("每家果商供应"+weight/num+"公斤水果");
            System.out.println("欢迎再来,预祝生意兴隆!");
        } catch (Exception e) {
            System.out.println("出现错误:采摘量和果商数应为整数,果商数应大于零!");
            e.printStackTrace();//输出完整异常信息
        }
    }
}

调用方法输出异常信息:printStackTrace();

1.1.3使用try-catch-finally语句处理异常

import java.util.Scanner;

public class Demo01 {
    public static void main(String[] args) {
        Scanner input=new Scanner (System.in);
        try {
            System.out.print("请输入果实采摘量(公斤)");
            int weight=input.nextInt();
            System.out.println("请输入果商数(家):");
            int num=input.nextInt();
            System.out.println("每家果商供应"+weight/num+"公斤水果");
            System.out.println("欢迎再来,预祝生意兴隆!");
        } catch (Exception e) {
            System.out.println("出现错误:采摘量和果商数应为整数,果商数应大于零!");
            e.printStackTrace();//输出完整异常信息
             System.exit(1);    //finally不被执行的唯一条件
        }finally {
            System.out.println("欢迎再来,祝老板生意兴隆");
        }
    }
}

finally的意思就是不管是否出现异常都会执行

注意: try语句块或catch语句块中添加了return语句,finally语句块也会被正常执行; System.exit(1); //finally不被执行的唯一条件

System.exit(1);的意思是中断程序,退出Java虚拟机

1.2 多重catch语句

1.2.1 语法:

try{
    //有可能会出现异常的语句
}catch(异常类型1 异常对象){
    //异常处理语句1
}catch(异常类型2 异常对象){
    //异常处理语句2
}finally{
    //一定会运行到的语句
}
  • 算数异常(ArithmeticException)
  • 输入类型不匹配异常(inputMismatch-Exception)

catch中Exception参数类型为以上两种异常的父类所以能够被该catch语句全部捕获,执行相同的异常处理程序,如果需要对可 能发生异常类型采取不同的处理方式就需要使用多个catch语句分别捕获不同的异常类型,输出不同的提示信息。最后一个catch语句使用Exception类型做参数,它可以处理前面的catch语句匹配的异常

1.2.2 代码示例:

import java.util.InputMismatchException;
import java.util.Scanner;

public class Demo01 {
    public static void main(String[] args) {
        Scanner input=new Scanner (System.in);
        try {
            System.out.print("请输入果实采摘量(公斤)");
            int weight=input.nextInt();
            System.out.println("请输入果商数(家):");
            int num=input.nextInt();
            System.out.println("每家果商供应"+weight/num+"公斤水果");
            System.out.println("欢迎再来,预祝生意兴隆!");
        } catch (ArithmeticException e) {//如果输入的果商数等于0或者小于0则会被ArithmeticException捕获
            System.out.println("出现错误:果商数应大于零!");
            e.printStackTrace();//输出完整异常信息

        }catch (InputMismatchException e){//如果输入的数据类型不匹配则会被InputMismatchException捕获
            System.out.println("出现错误:果实采摘量和果商数应为整数!");
            e.printStackTrace();
        }catch (Exception e){//如果不满足以上三种异常则会被Exception捕获
            System.out.println("未知异常");
            e.printStackTrace();
        }
        finally {
            System.out.println("欢迎再来,祝老板生意兴隆");
        }
    }
}

注意:

  • 当try语句块中发现异常时,系统将会按照从上到下的顺序依次检测每个catch语句,当匹配到某条catch语句后,后续的catch将不再被执行
  • 以Exceprion作为参数的catch语句必须放在最后的位置,否则所有的异常都会被其捕获,后面以其子类异常作为参数的catch语句将得不到被执行的机会。

1.2.3 异常分类以及处理流程

异常体系结构图

Throwable
Error
Exception
VirtulMechineError 虚拟机错误
AWTError
THreadEcath
RuntimeException
Checked异常
ArithmeticException算数异常
NullPointerException空指针异常
NumberFormatException
ClassCastException类型转换异常
ArrayIndexOutOfBoundsException数组下标越界异常
InputMismatchException类型转换异常
FileNotFoundException
EOFException
SQLException
  • Throwable他是Exception和Error的父类
  • Error仅靠程序本身无法恢复严重错误
  • Exception由Java应用程序抛出和处理的非严重错误
  • Checked程序必须处理该类异常

Excepiton类型的常用方法

方法名说 明
void printStackTrace()输出异常的堆栈信息
String getMessage()返回异常信息描述字符串,是printStackTrace()输出信息的一部分

提示:因为使用printStackTrace()方法输出的异常信息是最完整的,所以后续会使用该方法进行异常信息输出。在其输出结果后,可以自下向上观察程序的执行轨迹,最终定位到异常发生的位置

Java程序中常见的异常类型

异 常 类 型说 明
Exception异常层次结构的父类
ArithmeticException当出现算数错误时,抛出此异常。例如,在一个整数“除以0”时,抛出此异常
ArrayIndexOutOfBoundsException当非法索引访问数组时,抛出此异常。例如,索引为负或大于等于数组长度
NullPointerException当应用程序试图在需要对象的地方使用null时,抛出此异常
ClassNotFoundException不能加载所需的类
IllegalArgumentException当向方法传递了一个不合法或不正确的参数时,抛出此异常
ClassCastException当试图将对象强制转换为非本对象类型的子类时,抛出此异常
InputMismatchException欲得到的数据类型与实际输入的类型不匹配时,抛出此异常
NumberFormatException当试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出此异常。例如:把"ABC"转换为数字

check异常?

1.3声明异常—— throws关键字

throws关键字时方法可能抛出异常的声明,用在所声明的方法时,表示该方法可能会抛出此类异常

语法:

public void 方法名() throws 异常类型 [,异常类型]{
    //方法体
}

throws关键字可以在一个方法定义处声明一类或多类异常,多类异常间使用逗号分隔

1.3.1 使用throws关键字声明该方法中可能发生的异常

import java.util.Scanner;

public class Demo01 {
    public static void main(String[] args) {
        try {
            calculation();
        } catch (Exception e) {
            System.out.println("出现错误:采摘量和果商数应为整数,果商数应大于零!");
            e.printStackTrace();
        } finally {
            System.out.println("欢迎再来,预祝生意兴隆");
        }
    }
    public static void calculation() throws Exception {
        Scanner input=new Scanner (System.in);
        System.out.print("请输入果实采摘量(公斤)");
        int weight=input.nextInt();
        System.out.println("请输入果商数(家):");
        int num=input.nextInt();
        System.out.println("每家果商供应"+weight/num+"公斤水果");
        System.out.println("欢迎再来,预祝生意兴隆!");

    }
}

使用throw关键字声明多个异常

import java.util.InputMismatchException;
import java.util.Scanner;

public class Demo01 {
    public static void main(String[] args) {
        try {
            calculation();
        } catch (ArithmeticException e) {
            System.out.println("出现错误:果商数应大于零!");
            e.printStackTrace();
        }catch (InputMismatchException e){
            System.out.println("果商数和果子数量应该为整数");
            e.printStackTrace();
        }
        finally {
            System.out.println("欢迎再来,预祝生意兴隆");
        }
    }
    public static void calculation() throws ArithmeticException,InputMismatchException{
        Scanner input=new Scanner (System.in);
        System.out.print("请输入果实采摘量(公斤)");
        int weight=input.nextInt();
        System.out.println("请输入果商数(家):");
        int num=input.nextInt();
        System.out.println("每家果商供应"+weight/num+"公斤水果");
        System.out.println("欢迎再来,预祝生意兴隆!");

    }
}

**注意:**Main方法不建议声明异常,因为如果程序出现错误,会导致程序中断执行

1.3.2 抛出异常——throw关键字

语法

throw new 异类名(参数列表);  例如:throw new Exception()

使用throw关键字可以根据程序业务逻辑,自行抛出异常

1.4 日志框架Log4j 2

1.4.1 日志的主要用途

  • 问题追踪:辅助排查和定位问题,优化程序运行性能
  • 状态监控:通过日志分析,可以监控系统的运行状态
  • 安全审计:主要体现在安全上,可以发现非授权操作

1.4.2 常用的日志框架

  • Log4j:Apache Log4j是基于Java的日志记录工具,Log4j是几种Java日志框架之一
  • Commons Logging:Apache 基金会所属的项目,是一套Java日志接口
  • SLF4J:类似于Commons Logging,是一套简易Java日志门面,本身并无日志的实现
  • Logback:一套日志组件的实现(属于SLF4J阵营)
  • JUL(Java Util Logging):自Java1.4以来的官方日志实现
  • Log4j.2:Apache重写Log4j 1.x,成立新的项目Log4j 2。Log4j 2是Apache开发的一款升级产品

Log4j 2是一款非常优秀的日志框架,Log4j 2与Log4j相比发生了很大变化,日志的吞吐量及性能有很大的提升,解决了死锁的问题,配置更加简单灵活,他不兼容Log4j。Log4j 2具有Logback的所有特性

1.4.3 Log4j 2下载和配置

要使用Log4j 2,需要下载 Log4j 2 的.jar 文件,登录 Log4j 官网 https://logging.apache.org/log4j/2.x/下载 Log4j2压缩文件。本章以 Log4j 2.13.3 为例,压缩包为 apache-log4j-2.13-3-bin.zip,该文件的下载地址是 https://logging.apache.org/log4j/2.13.3/apache-log4j-2.13.3-bin.zip。该压缩包解压后将 log4j-api-2.13.3.jar 和 log4j-core-2.13.3.jar 两个jar 包导项目中。具体操作如下:

  • 在项目文件 src 文件夹中创建 lib 文件夹,将 Log4j-api-2.13.3.jar 和Log4j-core-2.13.3 jar 保存在其中
  • 在IntelliJ IDEA 开发环境中,执行“File”一“Project Structure”命令,打开“Projet Structure“(项目结构)对话框,选择“Modules”选项,在右侧窗格中选择,“Dependencies”选项卡后,单击右+”按钮,在打开的菜单中执行“JARs or directories”命令
  • 从 lib 文件夹中选择两个,jar 文件,单击“OK”按钮,将其添加到列表中并选中按钮,单击”OK“按钮

1.4.4 使用Logj 2记录日志

  1. 编写配置文件

    配置文件用来配置日志信息,自定义日志的输出位置、格式和内容。配置文件的扩展名可为.xml、.json或.jsn等。Log4j 2中没有默认的配置文件,需要手工创建,一般使用log4j2.xml命名配置文件。

  2. 定义日志记录器Logger

    在使用Log4j 2时,需要现在类中获取一个Logger对象,然后通过调用静态方法LogManager.getLogger()实现。这个Logger对象被称为日志记录器。获取日志记录器的方式如下

    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    //省略代码
    private static Logger 对象名=LogManager.getLogger(类名.class.getName());
    

    上边代码中使用getLogger()方法获取了一个Logger对象,该方法有一个String类型参数,使用”类名.class.getName()“获取当前类全名作为参数

  3. 记录日志

    Logger类可供开发人员记录日志信息,他提供了一系列方法来输出不同级别的日志信息,Logger类常用的日志记录方法如下:

    方法描述
    public void debug(Object msg)
    public void debug(Object msg,Throwable t)
    记录debug级别日志
    public void info(Object msg)
    public void info(Object msg,Throwable t)
    记录info级别日志
    public void warn(Object msg)
    public void warn(Object msg,Throwable t)
    记录warn级别日志
    public void error(Object msg)
    public void error(Object msg,Throwable t)
    记录error级别日志
    public void fatal(Object msg)
    public void fatal(Object msg,Throwable t)
    记录fatal级别日志

    日志级别共有八级,从低到高依次如下:

    all<trace<debug<info<warn<error<fatal<OFF

    • all:最低等级,用于打开所有日志记录
    • trace:用于程序追踪输出
    • debug:指出细粒度信息事件,对调试应用程序是非常有帮助的。
    • info:在粗粒度级别上指明消息,强调应用程序的运行过程
    • warn:表示警告信息,及可能出现的潜在错误
    • error:指出错误事件,但仍然不影响系统的继续运行
    • fatal:指出严重的错误事件,将会导致应用程序退出
    • OFF:最高等级,用于关闭所有日志记录

程序会输出高于或等于所设置级别的日志,设置的日志等级越高,输出的日志就越少。

log4j2.xml配置文件的各节点及其属性介绍

节点名称描述
configuration跟节点,其中可定义appenders节点和loggers节点,属性包含内容如下
status:可以用来执行Log4j 2本身打印日志的级别
monitorinterval:用来设置配置文件的动态加载时间,单位是秒,最小是5s
appenders日志输出目的地集合,包含Console,RollingFile,File三类appender节点,这些节点可配置日志输出位置
Console日志输出到控制台的配置节点,属性包含如下内容
name:指定节点名称
target:SYSTEM_OUT或SYSTEM_ERR,一般默认为SYSTEM_OUT
PatternLayout:设置输出格式
File日志输出到指定位置文件的配置节点,属性包含如下内容
name:指定appender名称
filename:指定输出日志的目的文件,必须是全路径的文件名
PatternLayout:输出格式,不设置时,默认为%m%n
loggersloggers节点集合,其常见字节点包含Root和Logger,可配置多个logger
root用来指定项目的根日志。如果没有单独的logger节点,则会默认按此节点配置进行日志输出
level:指出日志级别,从高到低有八个级别
logger用来单独指定日志的形式。例如,需要为包下的class指定不同的日志级别等。属性包含如下内容
name:指定该logger所使用的类或类所在包的全路径
lever:日志输出级别
appender-ref:指定日志输出的目标appender

提示

控制日志输出格式的常用占位符,通过设置日志输出格式,可以输出丰富多样化的日志。常用的占位符及其含义如下。

  • %d:用来设置输出日志的日期和时间,默认格式为 ISO8601。也可以在其后指定格式如%d{yyyy-MM-dd HH:mm:ss},输出的格式类似于 2021-03-10 16:43:08。
  • %m:输出代码中指定的消息。
  • %t:用来输出当前线程的名称
  • %5level:输出日志级别,-5 表示左对齐并固定输出5个字符,如果不足,则在右边补0
  • %1:用来输出日志事件的发生位置,包括类名、发生的线程,以及在代码中的行数。例如,如果输出为 cn.java.log.Test.main(Test.java:25),则说明日志事件发生在 cn.java.log 包下的Test类的 main 线程中,在代码中的行数为第25行
  • %logger:输出 logger 名称。
  • %msg:日志文本。
  • %n:换行。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值