linux 高阶函数 dynamic request ios4 vue案例 华为路由器ipv6配置 mysql删除一列 oracle连接字符串 linux查看jdk安装路径 python编程 java数据结构 java中的接口 javaif语句 java中class java自定义异常 java中collection js选项卡 groupby 简体中文语言包 abaqus最新版本 phpqrcode 如何给黑白照片上色 assist是什么意思 JScodeblocks汉化包 图片轮播代码 php递归 dos系统下载 ip地址切换器 截取字符串 金水疑云 php保留两位小数 小米手机开发者模式 取小数点后两位函数 ps描边怎么用 昌江县干部在线学习 qq个人文件夹清理 决战者 华为虚拟按键 mysql下载64位
当前位置: 首页 > 学习教程  > 编程语言

Java笔记3-异常处理

2020/7/24 9:58:11 文章标签:

目录

  • Java的异常
  • 捕获异常
  • 抛出异常
  • 自定义异常
  • NullPointerException
  • 使用断言
  • 使用 JDK Logging
  • 使用 Commons Logging
  • 使用 Log4j
  • 使用 SLF4J 和 Logback

笔记摘自 廖雪峰的官方网站- 异常处理。

Java的异常

Java使用异常来表示错误,并通过try … catch捕获异常;

try {
    String s = processFile(“C:\\test.txt”);
    // ok:
} catch (FileNotFoundException e) {
    // file not found:
} catch (SecurityException e) {
    // no read permission:
} catch (IOException e) {
    // io error:
} catch (Exception e) {
    // other error:
}

Java的异常是class,并且从Throwable继承;
在这里插入图片描述

Error是无需捕获的严重错误,Exception是应该捕获的可处理的错误;

RuntimeException无需强制捕获,非RuntimeException(Checked Exception)需强制捕获,或者用throws声明;

不推荐捕获了异常但不进行任何处理,即使真的什么也做不了,也要先把异常记录下来。

static byte[] toGBK(String s) {
    try {
        return s.getBytes("GBK");
    } catch (UnsupportedEncodingException e) {
        // 先记下来再说:
        e.printStackTrace();
    }
    return null;

所有异常都可以调用printStackTrace()方法打印异常栈,这是一个简单有用的快速打印异常的方法。

捕获异常

使用try … catch … finally时:

  • 多个catch语句的匹配顺序非常重要,子类必须放在前面;
  • 多个catch语句只有一个能被执行;
  • finally语句保证了有无异常都会执行,它是可选的;
  • 一个catch语句也可以匹配多个非继承关系的异常。
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (UnsupportedEncodingException e) {
        System.out.println("Bad encoding");
    } catch (IOException e) {
        System.out.println("IO error");
    } finally {
        System.out.println("END");
    }
}
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException | NumberFormatException e) { // IOException或NumberFormatException
        System.out.println("Bad input");
    } catch (Exception e) {
        System.out.println("Unknown error");
    }
}

抛出异常

详情见 抛出异常 。

如何抛出异常?抛出异常分两步:

  • 创建某个Exception的实例;
  • 用throw语句抛出。

下面是一个例子:

void process2(String s) {
    if (s==null) {
        NullPointerException e = new NullPointerException();
        throw e;
    }
}

简化为一行:

void process2(String s) {
    if (s==null) {
        throw new NullPointerException();
    }
}

调用printStackTrace()可以打印异常的传播栈,对于调试非常有用;

捕获异常并再次抛出新的异常时,应该持有原始异常信息;

通常不要在finally中抛出异常。如果在finally中抛出异常,应该原始异常加入到原有异常中。调用方可通过Throwable.getSuppressed()获取所有添加的Suppressed Exception。

自定义异常

抛出异常时,尽量复用JDK已定义的异常类型;

自定义异常体系时,推荐从RuntimeException派生“根异常”,再派生出业务异常;

自定义异常时,应该提供多种构造方法。

Java标准库定义的常用异常包括
Java标准库定义的常用异常,忽略水印
在一个大型项目中,可以自定义新的异常类型,但是,保持一个合理的异常继承体系是非常重要的。

一个常见的做法是自定义一个BaseException作为“根异常”,然后,派生出各种业务类型的异常。

BaseException需要从一个适合的Exception派生,通常建议从RuntimeException派生:

public class BaseException extends RuntimeException {
}

其他业务类型的异常就可以从BaseException派生:

public class UserNotFoundException extends BaseException {
}

public class LoginFailedException extends BaseException {
}

...

自定义的BaseException应该提供多个构造方法:

public class BaseException extends RuntimeException {
    public BaseException() {
        super();
    }

    public BaseException(String message, Throwable cause) {
        super(message, cause);
    }

    public BaseException(String message) {
        super(message);
    }

    public BaseException(Throwable cause) {
        super(cause);
    }
}

上述构造方法实际上都是原样照抄RuntimeException。这样,抛出异常的时候,就可以选择合适的构造方法。通过IDE可以根据父类快速生成子类的构造方法。

NullPointerException

NullPointerException是Java代码常见的逻辑错误,应当早暴露,早修复;

NullPointerException即空指针异常,俗称NPE。如果一个对象为null,调用其方法或访问其字段就会产生NullPointerException。

public class Main {
    public static void main(String[] args) {
        String s = null;
        System.out.println(s.toLowerCase());
    }
}

可以启用Java 14的增强异常信息来查看NullPointerException的详细错误信息。

处理详情见 NullPointerException 。

使用断言

断言(Assertion)是一种调试程序的方式。在Java中,使用assert关键字来实现断言。

public static void main(String[] args) {
    double x = Math.abs(-123.45);
    assert x >= 0 : "x must >= 0";
    System.out.println(x);
}

语句assert x >= 0;即为断言,断言条件x >= 0预期为true。如果计算结果为false,则断言失败,抛出AssertionError。

断言失败的时候,AssertionError会带上消息x must >= 0,更加便于调试。

Java断言的特点是:断言失败时会抛出AssertionError,导致程序结束退出。因此,断言不能用于可恢复的程序错误,只应该用于开发和测试阶段。

对可恢复的错误不能使用断言,而应该抛出异常;

断言很少被使用,更好的方法是编写单元测试。

使用 JDK Logging

Java标准库内置了日志包 java.util.logging 。

// logging
import java.util.logging.Level;
import java.util.logging.Logger;
public class Hello {
    public static void main(String[] args) {
        Logger logger = Logger.getGlobal();
        logger.info("start process...");
        logger.warning("memory is running out...");
        logger.fine("ignored.");
        logger.severe("process will be terminated...");
    }
}

日志的输出可以设定级别。JDK的Logging定义了7个日志级别,从严重到普通:

  • SEVERE
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST
    日志是为了替代System.out.println(),可以定义格式,重定向到文件等;

日志可以存档,便于追踪问题;

日志记录可以按级别分类,便于打开或关闭某些级别;

可以根据配置文件调整日志,无需修改代码;

Java标准库提供了java.util.logging来实现日志功能。

使用 Commons Logging

Commons Logging是一个第三方日志库,它是由Apache创建的日志模块,可以作为“日志接口”来使用。

Commons Logging定义了6个日志级别:

  • FATAL
  • ERROR
  • WARNING
  • INFO
  • DEBUG
  • TRACE

默认级别是INFO。

Commons Logging是使用最广泛的日志模块;

Commons Logging的API非常简单;

Commons Logging可以自动检测并使用其他日志模块。

详情见 Commons Logging 。

使用 Log4j

Log4j是一种非常流行的日志框架,详情见 使用Log4j 。
在开发阶段,始终使用Commons Logging接口来写入日志,并且开发阶段无需引入Log4j。如果需要把日志写入文件, 只需要把正确的配置文件和Log4j相关的jar包放入classpath,就可以自动把日志切换成使用Log4j写入,无需修改任何代码。

使用 SLF4J 和 Logback

SLF4J和Logback可以取代Commons Logging和Log4j;

始终使用SLF4J的接口写入日志,使用Logback只需要配置,不需要修改代码。

详情见 使用SLF4J和Logback 。


本文链接: http://www.dtmao.cc/news_show_50182.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?