java基础(12)(异常,异常体系结构,异常处理,自定义异常,log4j的作用)

异常

异常介绍

异常是指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。

程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。

在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。

异常体系

异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Errorjava.lang.Exception,平常所说的异常指java.lang.Exception

Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。

Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎。

异常的层次

所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
Error 用来指示运行时环境发生的错误。

异常的分类

检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

JVM处理异常过程分析

异常处理

一、在一个方法中,有多个异常,使用try...catch进行处理:
*          写多个try...catch
*          一个try对应多个catch , 多个catch之间的执行流程
*          一个try...catch

*          try...catch...finally

二、throws

throws方式处理异常 又被称之为声明异常,将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。

关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常)

修饰符 返回值类型 方法名() throws 异常类名 {
    
}

try...catch.finally案例

/**
 * @Describe
 * @Author Double LiFly
 * @date 2021/4/21 14:31
 */
public class Exception07 {
    public static void main(String[] args) {
        int sum = getSum();
        System.out.println(sum);
    }
    public static int getSum(){
        try {
            int sum = 10+20;
            return sum;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return 40;//始终返回40,
        }
    }
}

throws代码案例

/**
 * @Describe
 * @Author Double LiFly
 * @date 2021/4/21 14:13
 */
public class Exception05 {
    public static void main(String[] args) throws Exception {
        method1();
    }
    /**
     * 直接throws 以下异常的父类
     * @throws Exception
     */
    public static void method1()throws Exception{
        Class<?> clazz = Class.forName("");
        Method method = clazz.getMethod("", String.class);
        FileInputStream fis = new FileInputStream(new File(""));
        fis.close();
    }

    /**
     * 依次抛出各自的异常
     * @throws ParseException
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static void method()throws ParseException, FileNotFoundException, IOException {
        SimpleDateFormat sdf = new SimpleDateFormat("");
        sdf.parse("");
        FileInputStream fis = new FileInputStream(new File(""));
        fis.close();
    }
}

Throwable类中常见方法

public String getMessage();返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。
public String toString();使用getMessage()的结果返回类的串级名字。
public void printStackTrace();打印toString()结果和栈层次到System.err,即错误输出流。

/**
 * @Describe
 * @Author Double LiFly
 * @date 2021/4/21 14:24
 */
public class ThrowableDemo01 {
    public static void main(String[] args) {
        try {
            int result = 2/0;
            System.out.println(result);
        } catch (Exception e) {
            System.out.println(e.getMessage());//获得异常的原因
            System.out.println(e.toString());//获得异常的类型和原因
            e.printStackTrace();//获得异常的类型,原因和位值
        }
    }
}

异常的注意事项

throws关键字必须写下方法的声明上
throws关键字后面声明的异常的类型必须是Exception或者Exception的子类
如果方法内抛出了多个异常对象,那么throws后便必须声明多个异常
如果抛出的异常类型是由父子关系,直接声明父类即可
调用一个声明抛出异常的方法,我们就必须处理这个异常
要么使用throws抛出异常,交给JVM处理【该方式不建议使用】
要么使用try。。。catch自己处理

自定义异常

一个类继承了java.lang.Exceptionjava.lang.RuntimeException类,那么这个类就是一个异常类

public class 异常类 extends Exception | RuntimeException {
    public 异常类() {
    }

    public 异常类(String message) {
        super(message);
    }
}

自定义异常小案例

/**
 * @Describe
 * @Author Double LiFly
 * @date 2021/4/21 14:49
 */
public class RegisterException extends Exception {
    public RegisterException(){}
    public RegisterException(String message){
        super(message);
    }
}
/**
 * @Describe
 * @Author Double LiFly
 * @date 2021/4/21 14:42
 */
public class ExceptionClassTest {
    private static String [] names = {"bill","hill","jill"};
    public static void main(String[] args) {
        try {
            checkUserName("bill");
            System.out.println("注册成功");
        } catch (RegisterException e) {
            e.printStackTrace();
        }

    }
    public static boolean checkUserName(String uname) throws RegisterException {
        for (String name :names) {
            if (name.equals(uname)){
                throw new RegisterException("亲"+name+"已经被注册了");
            }
        }
        return true;
    }
}

throw与throws区别

        throws                                                                                   throw
        用在方法声明后面,跟的是异常类型                                    用在方法体内,跟的是异常对象名
        表示抛出异常,由该方法的调用者来处理                             表示抛出异常,由方法体内的语句处理
        表示出现异常的一种可能性,并不一定会发生这些异常        执行throw一定抛出了某种异常

Log4J

日志

日志用来记录用户操作、系统运行状态等,是一个系统的重要组成部分。对于一些简单的小程序,可能并不需要在如何记录日志的问题上花费太多精力。但是对于作为基础平台为很多产品提供服务的后端程序,就必须要考虑如何依靠良好的日志来保证系统可靠的运行了。

==好的日志可以帮助系统的开发和运维人员:==

  • 了解线上系统的运行状态

  • 快速准确定位线上问题

  • 发现系统瓶颈

  • 预警系统潜在风险

  • 挖掘产品最大价值

==不好的日志导致:==

  • 对系统的运行状态一知半解,甚至一无所知

  • 系统出现问题无法定位,或者需要花费巨大的时间和精力

  • 无法发现系统瓶颈,不知优化从何做起

  • 无法基于日志对系统运行过程中的错误和潜在风险进行监控和报警

  • 对挖掘用户行为和提升产品价值毫无帮助

日志分类

日志的分类
    从功能上分:诊断日志,统计日志,审计日志
    诊断日志,典型有
        - 请求入口和出口
        - 外部服务调用和返回
        - 资源消耗操作: 如读写文件等
        - 容错行为: 如云硬盘的副本修复操作
        - 程序异常: 如数据库无法连接
        - 后台操作:定期执行删除的线程
        - 启动、关闭、配置加载
    统计日志
        - 用户访问统计:用户IP、上传下载的数据量,请求耗时等
        - 计费日志(如记录用户使用的网络资源或磁盘占用,格式较为严格,便于统计)
    审计日志
       管理操作

日志的等级

Log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。

  • ==ALL==

    最低等级的,用于打开所有日志记录。

  • ==TRACE==

    designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。

  • ==DEBUG==

    DEUBG 级别的主要输出调试性质的内容,该级别日志主要用于在开发、测试阶段输出。该级别的日志应尽可能地详尽,便于在开发、测试阶段出现问题或者异常时,对其进行分析。

  • ==INFO==

    INFO日志主要记录系统关键信息,旨在保留系统正常工作期间关键运行指标,开发人员可以将初始化系统配置、业务状态变化信息,或者用户业务流程中的核心处理记录到INFO日志中,方便日常运维工作以及错误回溯时上下文场景复现。建议在项目完成后,在测试环境将日志级别调成 INFO,然后通过 INFO 级别的信息看看是否能了解这个应用的运用情况,如果出现问题后是否这些日志能否提供有用的排查问题的信息。

  • ==WARN==

    WARN 级别的主要输出警告性质的内容,这些内容是可以预知且是有规划的,比如,某个方法入参为空或者该参数的值不满足运行该方法的条件时。在 WARN 级别的时应输出较为详尽的信息,以便于事后对日志进行分析

  • ==ERROR==

    ERROR 级别主要针对于一些不可预知的信息,诸如:错误、异常等,比如,在 catch 块中抓获的网络通信、数据库连接等异常,若异常对系统的整个流程影响不大,可以使用 WARN 级别日志输出。在输出 ERROR 级别的日志时,尽量多地输出方法入参数、方法执行过程中产生的对象等数据,在带有错误、异常对象的数据时,需要将该对象一并输出

  • ==FATAL==

    指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。

  • ==OFF==

    最高等级的,用于关闭所有日志记录。

    日志小结

如果将log level设置在某一个级别上,那么比此级别优先级高的log都能打印出来。例如,如果设置优先级为WARN,那么OFF、FATAL、ERROR、WARN 4个级别的log能正常输出,而INFO、DEBUG、TRACE、 ALL级别的log则会被忽略。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。

==Log4J的默认级别为:ERROR==

Log4J概述

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台文件等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。在apache网站:jakarta.apache.org/log4j 可以免费下载到Log4j最新版本的软件包。

使用

1.导包

log4j.jar以及配置文件

2.导入配置文件

3.测试

/**
 * @Describe
 * @Author Double LiFly
 * @date 2021/4/21 15:02
 */
public class Log4JDemo {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Log4JDemo.class);
        logger.debug("debug模式输出");
        logger.info("info模式输出");
        logger.warn("warn模式输出");
        logger.error("error模式输出");
    }
}

log4j配置文件解析

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

double_lifly

点喜欢就是最好的打赏!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值