Java中异常打印输出的常见方法总结

发布时间 - 2026-01-11 02:12:05    点击率:

前言

Java异常是在Java应用中的警报器,在出现异常的情况下,可以帮助我们程序猿们快速定位问题的类型以及位置。但是一般在我们的项目中,由于经验阅历等多方面的原因,依然有若干的童鞋在代码中没有正确的使用异常打印方法,导致在项目的后台日志中,没有收到日志或者日志信息不完整等情况的发生,这些都给项目埋下了若干隐患。本文将深入分析在异常日志打印过程中的若干情况,并给出若干的使用建议。

1. Java异常Exception的结构分析

我们通常所说的Exception主要是继承于Throwable而来,可以参见如下的结构图示:

主要的Throwable分为异常和错误两种,然后异常Exception和错误Error做为基类,分别被具体个性化以及衍生出NullPointerException、EOFException等等异常信息类。

基于Java中的源代码来分析,Error和Exception仅仅是继承了Throwable,做了构造函数的拓展,没有进行额外方法的延展;Exception输出的主要核心方法都是定义在Throwable中的,感兴趣的童鞋可以尝试阅读JDK的源代码。

下面将介绍一下关键的几个异常类方法:

1、getMessage(): String

输出异常的描述信息

2、getLocalizedMessage()

输出本地化的描述信息,一般此方法可被子类所覆盖,缺省实现与getMessage()输出信息一致

3、printStackTrace()

将异常栈打印到输出流中,此为一类方法,默认打印到console控制台,也可以显式指定输出流。

4、fillInStackTrace()

将当前的异常栈保存到一个Throwable中,返回这个Throwable。大部分情况下,用在保留异常栈嵌套调用的情况,尝试保留完整的异常栈,无需使用该方法。

2. Error vs Exception

Error在Java体系中定义为不可控制的问题,往往用来描述系统错误或者底层的问题,比如虚拟机错误,例如内存空间不足,方法调用栈溢等。我们以上图中列举出的内存溢出错误(StackOverflowError)为例,它是在JVM层面发生的错误,已经游离于java应用层之外;在应用程序层面是无法进行捕获,且无法从错误中恢复的。一般一旦发了类似问题,一般都是直接宕机,应用停止正常的工作,需要重新启动或者修复问题之后,方可重新正常工作。

Exception一般发生在应用层,即在由项目中的Java代码层面引发的问题,且可以尝试进行捕获,此类问题不会影响到应用程序的正常工作的,即不会导致宕机现象的发生。我们在工作或者代码中常见的都是Exception衍生出来的各类异常。

这里需要强调说明一下,JVM是Java语言的运行环境和平台,但是并不是Java语言体系的一个部分;在JVM平台上,还可以运行Groovy, JPython, JRuby, Closure,Scala等等遵守Java语言规范(JavaLanguage Specification)的编程语言,故我们可以将Error理解为脱离Java应用之外的问题。

3. Exception中的运行时异常(RuntimeException)和受控异常(checked exception)

运行时异常(RuntimeException)是指在运行之时发生的异常,无需显式地进行捕获;如果程序中发生类似的异常,JVM会直接抛出此类异常,并打出响应的异常栈信息。此类异常也通常被称为unchecked exception, 未受控异常。

受控异常(checked Exception)是我们最常见的异常种类,在代码中使用的异常基本上都是此类异常,此类异常会在代码编译阶段由Java编译器进行语法检查,如果未显式进行异常捕获,则会报出相应的编译异常信息。

4. 如何在代码中正确打印异常信息

下面我们将通过一系列的例子来说明上述几个Exception中方法的使用技巧。

Case 1: getMessage()/getLocalizedMessage()

public void testCase1() {
System.out.println("We are going to do something interesting....");
try {
throw new NullPointerException("I am an exception in the code.");
} catch (Exception e) {
System.out.println("We got unexpected:" + e.getMessage());
System.out.println("We got unexpected:" + e.getLocalizedMessage());
}
}

输出结果:

We are going to do testing interesting....
We got unexpected in getMessage==> I am an exception in the code.
We got unexpected in getLocalizedMessage==> I am an exception in the code.

基于结果来分析, 上述两个方法只是将异常对象中的Message打印出来,这些信息对于我们追踪问题和调试帮助有限。

Case 2:e.printStackTrace()

public void testCase2() {
System.out.println("We are going to do something interesting....");
try {
throw new Exception("I am an exception in the code.");
} catch (Exception e) {
e.printStackTrace();
}
}

运行结果:

运行结果图

printStackTrace()可以打印出整个异常栈,但是异常栈信息将输出到默认的输出流中,绝大多数情况下是系统的控制台,而在实际项目中,都是需要将异常栈输出到日志文件的,如果不显式指定,则会丢失异常信息,在日志文件中无从追查。

Case 3: 基于log4j/slf4j等输出到日志文件

在实际项目中,一般会使用log4j/log4j2/JDK logging/slf4j/logback等日志系统来存放日志,那如何来讲日志的异常栈存入日志文件呢,我们来看示例。

public void testCase3() {
System.out.println("We are going to do something interesting....");
try {
throw new NullPointerException("abcedfeg");
} catch (Exception e) {
logger.info("Unexpected error in ", e);
}
}

我们需要到日志文件中,找到相应的异常信息,异常信息如下:

12:24:45.387 [main] INFO org.demo.TestException - Unexpected error in
java.lang.NullPointerException: abcedfeg
at org.demo.TestException.testCase3(TestException.java:39)
at org.demo.TestException.main(TestException.java:12)

我们可以发现,整个异常栈信息由两个部分组成:

>> 异常中的message, 类似getMessage()输出的信息,

>> 使用logger.info之类的方法,将异常信息写入到日志流中.

以下为log4j的声明,这里以slf4j为例来示例:

private static final Logger logger = LoggerFactory.getLogger(TestException.class); 

Case 4: fillInStackTrace()

public class FillInExceptionTest {
public static void main(String[] args) {
FillInExceptionTest fit = new FillInExceptionTest();
try {
fit.outerMehtod();
} catch (Exception e) {
System.out.println("\n==========I am the one evil separation line==============");
e.printStackTrace();
}
}
public void innerMethod() throws Exception {
throw new Exception("I got exception in an inner method.");
}
public void outerMehtod() throws Exception {
try {
innerMethod(); //invoke inner method.
} catch (Exception e) {
e.printStackTrace();
throw (Exception)e.fillInStackTrace();
}
}
}

运行结果:

基于上述的运行结果可知,fillInStackTrace()只提取了当下的异常栈信息,而非完整的异常栈信息,这个就是此方法带给我们的特殊之处。

如果我们需要在最外层将完整的异常栈打印出来,该如何做呢? 将下述的语句:

throw (Exception)e.fillInStackTrace();

替换为:

throw e;

重新运行程序,我们就可以在最外层得到完整的异常栈信息了。

5. 总结

在本文中,我们介绍了异常类的继承体系,不同类型的异常区别与使用场景;并将基于代码示例展示了如何使用Exception的若干方法,利用这些方法来保留尽可能多的日志信息,方便我们后续针对日志中的异常信息,追查和解决问题。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。


# java打印输出  # java  # 异常  # 异常处理  # Java程序常见异常及处理汇总  # 浅谈java中异常抛出后代码是否会继续执行  # 简单了解Java编程中抛出异常的方法  # 一篇文章详解Java异常处理  # 都是  # 此类  # 几个  # 是在  # 我们可以  # 情况下  # 为例  # 则会  # 源代码  # 应用程序  # 打印出来  # 童鞋  # 应用层  # 运行环境  # 好了  # 最外层  # 还可以  # 之处  # 是指  # 两种 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel怎么集成Vue.js_Laravel Mix配置Vue开发环境  Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  青岛网站建设如何选择本地服务器?  Laravel如何实现API版本控制_Laravel版本化API设计方案  如何在建站宝盒中设置产品搜索功能?  JavaScript如何实现继承_有哪些常用方法  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  Laravel如何使用Passport实现OAuth2?(完整配置步骤)  php静态变量怎么调试_php静态变量作用域调试技巧【解答】  重庆市网站制作公司,重庆招聘网站哪个好?  新三国志曹操传主线渭水交兵攻略  Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置  Internet Explorer官网直接进入 IE浏览器在线体验版网址  在centOS 7安装mysql 5.7的详细教程  Laravel如何使用Blade模板引擎?(完整语法和示例)  Javascript中的事件循环是如何工作的_如何利用Javascript事件循环优化异步代码?  Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性  简单实现Android文件上传  网站视频制作书签怎么做,ie浏览器怎么将网站固定在书签工具栏?  为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】  如何利用DOS批处理实现定时关机操作详解  如何破解联通资金短缺导致的基站建设难题?  HTML 中如何正确使用模板变量为元素的 name 属性赋值  Laravel如何清理系统缓存命令_Laravel清除路由配置及视图缓存的方法【总结】  如何在宝塔面板创建新站点?  Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能  如何获取免费开源的自助建站系统源码?  香港服务器租用费用高吗?如何避免常见误区?  UC浏览器如何设置启动页 UC浏览器启动页设置方法  如何在搬瓦工VPS快速搭建网站?  中山网站制作网页,中山新生登记系统登记流程?  Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  手机怎么制作网站教程步骤,手机怎么做自己的网页链接?  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出  微信小程序 canvas开发实例及注意事项  Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】  Windows10如何删除恢复分区_Win10 Diskpart命令强制删除分区  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  如何在宝塔面板中修改默认建站目录?  如何用AWS免费套餐快速搭建高效网站?  微信小程序 HTTPS报错整理常见问题及解决方案  无锡营销型网站制作公司,无锡网选车牌流程?  Python函数文档自动校验_规范解析【教程】  成都网站制作公司哪家好,四川省职工服务网是做什么用?  html5源代码发行怎么设置权限_访问权限控制方法与实践【指南】  标题:Vue + Vuex 项目中正确使用 JWT 进行身份认证的实践指南  详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)