1、异常是什么

异常:

1、就是不正常的意思:
2、指程序在执行过程中,出现的非正常的情况,最终导致jvm非正常停止
3、在java等面向对象的编程语言中,异常本身就是一个类,产生异常就是创建一个异常对象并抛出了一个异常对象,java处理异常的方式就是中断处理
4、异常指的并不是语法错误。语法错误,编译通过不了的,不会产生字节码文件根本不能运行

异常的体系:

异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Error与java.lang.Exception,平常所说的异常指java.lang.Exception
异常体系:
Throwable体系:
Error: //错误
严重错误,无法通过处理的错误,只能事先避免,好比绝症
Exception: //异常
异常产生后可以通过代码的方式纠正,使程序继续运行,且必须处理,好比感冒
RuntimeException //运行时异常
runtime异常:在运行时期检查异常,在编译时期不会被编译器检测(不报错)如数学异常
非RuntimeException //非运行时异常
checked异常:在编译时期就会被检测到,如果不处理异常,则编译失败

2、异常怎么处理

JVM默认处理异常的方式:

如果程序出现了问题,我们没有做任何处理,最终JVM会做默认处理
1、把异常的名称,错误原因及异常出现的位置等信息输出在控制台
2、程序停止执行

try-catch方式处理异常:

定义格式:

  1. try {
  2. /可能出现异常的代码;
  3. } catch(异常类名 变量名) {
  4. //异常的处理代码;
  5. }
  6. 执行流程:
  7. 1、程序从try里面的代码开始执行
  8. 2、出现异常,就会跳转到对应的catch里面执行
  9. 3、执行完毕之后,程序还可以继续往下执行

throws方式处理异常:

throws处理异常,又被称之为声明异常,将问题标识出来,,报告给调用者
用于表示当前方法不处理异常,而是提醒该方法的调用者处理异常(抛出异常)
声明异常的格式:

  1. 修饰符 返回值类型 方法名() throws 异常类名 {
  2. //这是一个正常的可能出现异常的方法
  3. }

常见方法:
getMessage():获取异常的原因
toString():获取异常的类型和原因
pintStackTrace:获取异常的类型,原因和位置

finally代码块:

有一些特定的代码无论异常是否发生,都需要执行,异常会引发程序跳转,导致后续的代码执行不到,,而finally存放的代码都是一定会被执行的
格式如下:

  1. try {
  2. 可能出现异常的代码;
  3. } catch(异常类名 变量名) {
  4. 异常的处理代码;
  5. } finally{
  6. 释放资源
  7. }
  8. 1finally不能单独使用。必须配合着try...catch使用
  9. 2、当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。

父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出

3、自定义异常

一个类继承了Exception或者RuntimeException,那么这个类就是异常类

  1. public class 异常类 extends Exception | RuntimeException {
  2. public 异常类() {
  3. }
  4. public 异常类(String message) {
  5. super(message);
  6. }
  7. }

自定义异常代码实现:

  1. // 业务逻辑异常
  2. public class RegisterException extends Exception {
  3. /**
  4. * 空参构造
  5. */
  6. public RegisterException() {
  7. }
  8. /**
  9. *
  10. * @param message 表示异常提示
  11. */
  12. public RegisterException(String message) {
  13. super(message);
  14. }
  15. }
  16. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  17. public class Demo {
  18. // 模拟数据库中已存在账号
  19. private static String[] names = {"bilibili","bilibili","bilibili"};
  20. public static void main(String[] args) {
  21. //调用方法
  22. try{
  23. // 可能出现异常的代码
  24. checkUsername("bilibili");
  25. System.out.println("注册成功");//如果没有异常就是注册成功
  26. }catch(RegisterException e){
  27. //处理异常
  28. e.printStackTrace();
  29. }
  30. }
  31. //判断当前注册账号是否存在
  32. //因为是编译期异常,又想调用者去处理 所以声明该异常
  33. public static boolean checkUsername(String uname) throws RegisterException{
  34. for (String name : names) {
  35. if(name.equals(uname)){//如果名字在这里面 就抛出登陆异常
  36. throw new RegisterException("亲"+name+"已经被注册了!");
  37. }
  38. }
  39. return true;
  40. }
  41. }

4、Log4J

日志用来记录用户操作,系统运行状态等,是一个系统的重要组成部分,对于一些简单的小程序,可能不需要在如何记录日志的问题发费太多的精力,作为一个大的程序,要保证长久的运行,就必须考虑日志记录了,依靠良好的日志来保证程序可靠的运行
好的日志:
1、了解线上系统的运行状态
2、快速准确定位线上问题
3、发现系统瓶颈
4、预警系统潜在风险
5、挖掘产品最大价值
不好的日志:
1、对系统的运行状态一知半解,甚至一无所知
2、系统出现的问题无法定位,或者发挥巨大的时间和精力
3、无法发现系统瓶颈,不知优化从何做起
4、无法基于日志对系统运行过程中的错误和潜在风险进行监控和报警
5、对挖掘用户行为和提升产品价值毫无帮助

日志分类:

诊断日志:

1、请求入口和出口
2、外部服务调用和返回
3、资源消耗操作:如读取文件等
3、容错行为:如云硬盘的副本修复操作
4、程序异常:如数据库无法连接
5、后台操作:定期执行删除的线程
6、启动,关闭,配置加载

统计日志:

1、用户访问统计:用户IP,上传下载的数据量和请求耗时等
2、计费日志(如记录用户使用的网络资源或磁盘占用,格式较为严格,便于统计)

审计日志:

对于简单的系统,可以将所有的日志输出到同一个日志文件中,通过不用的关键字进行区分,而对于复杂的系统,将不同需求的日志文件输出到不同的日志文件中是必要的

日志级别:

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

ALL:

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

TRACE:

很低的日志级别,一般不会使用

DEBUG:

主要是输出调试性质的内容,主要用于开发和测试阶段的输出

INFO:

主要记录系统关键信息,保留系统正常工作期间运行指标

WARN:

主要输出警告性质的内容,这些内容是可以预知且是有规划的

ERROR:

主要针对一些不可预知的信息,诸如:错误,异常等(log4J默认级别)

FATAL:

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

OFF:

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

Log4J使用

1、导包
2、导配置文件:log4j.properties

  1. ### 设置###
  2. log4j.rootLogger = debug,stdout,D,E
  3. ### 输出信息到控制抬 ###
  4. log4j.appender.stdout = org.apache.log4j.ConsoleAppender
  5. log4j.appender.stdout.Target = System.out
  6. log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
  7. log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
  8. ### 输出DEBUG 级别以上的日志到=log4j.appender.D.File =要保存日志的位置 ###
  9. log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
  10. log4j.appender.D.File = G://logs/debug.log
  11. log4j.appender.D.Append = true
  12. log4j.appender.D.Threshold = DEBUG
  13. log4j.appender.D.layout = org.apache.log4j.PatternLayout
  14. log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
  15. ### 输出ERROR 级别以上的日志到=log4j.appender.E.File =要保存日志的位置 ###
  16. log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
  17. log4j.appender.E.File =G://logs/error.log
  18. log4j.appender.E.Append = true
  19. log4j.appender.E.Threshold = ERROR
  20. log4j.appender.E.layout = org.apache.log4j.PatternLayout
  21. log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

3、记录日志代码

  1. public class Log4JDemo {
  2. public static void main(String[] args) {
  3. // 获取日志记录器对象
  4. Logger logger = null;
  5. try {
  6. logger = Logger.getLogger(Log4JDemo.class);
  7. int i = 4 / 0;
  8. } catch (Exception e) {
  9. //记录日志信息
  10. logger.debug(e.getMessage());
  11. }
  12. }
  13. }