【语言基础NO.00001】Java的异常处理机制 by arttnba3

0x00.绪论-什么是异常处理?

异常处理(exceptional handling)是OOP中十分重要的一个概念,相比于以往的预先针对预期错误情况设计的error code模式而言,异常处理的模式更加清晰,不仅分离了错误代码,还能帮助开发者更好地审计代码错误,方便阅读与维护。作为现代化的OOP程序设计语言,Java同样有着属于自己的异常处理机制。

异常(Exception)指的是程序运行过程中可能会发生的一些错误,通常分为以下两类:

  • 检查性异常(Checked Error Exception):编译器可以直接预见的运行当中可能会出现的问题,比如Java程序在打开文件时可能会发现文件不存在,JVM就会抛出FileNotFoundException异常,这类异常是需要我们使用try和catch类进行捕获的

  • 运行时异常(Runtime Error Exception):又叫非检查性异常,即编译器无法直接检查出来的异常,如new C programmer常常出现的指针访问非法内存区域、栈溢出等。

这篇文章是CSDN特供的,arttnba3.cn没有的哦XD
顺便CSDN的markdown用着属实恼火😡

0x01.简单的异常处理机制

现代的OOP的异常处理机制通常如下:

  • 对于可能出现异常的被调用代码段,由其本身针对异常情况设计相应的异常类,并在遇到异常情况时抛出异常
  • 调用方在调用可能出现异常的方法时针对出现异常的方法抛出的异常进行捕获,并解决该问题使程序可以正常地继续运转
  • 打印异常使开发者可以更好地审计与修正代码

我们可以使用如下的伪代码进行表示:

/*
*
* Copyright(C) 2020 arttnba3. All rights reserved
*
*/

//definition of ExceptionalHandlingExampleException
...
class ExceptionalHandlingExampleException extends Exception
{
...
private:
	...
	saved_data;//which we use to save our data when errors occur
public :
	...
	function printStackTrace();//which we use to print the log recoding how error occurs
}
...
//the function which may occur errors, we made it throw Exception
function possiblyErrorFunction() throws ExceptionalHandlingExampleException
{
	...
	/*where error may occur*/
	if(error_occur)
	{
		code_deling_errors;//selectable
		throws ExceptionalHandlingExampleException;//when error occurs, we throw Exception back to the caller of program
	}
}
...
//where we may call the function
try
{
	...
	possiblyErrorFunction();//if it doesn run correctly, the program'll stop there and jump out
	...
}
catch(ExceptionalHandlingExampleException excception)//if an Exception was caught, code there will be run
{
	code_dealing_with_exception;
	exception.printStackTrace();//selectable, but you should do it
}
finally//selectable code, which will always be run
{
	...
}

以上的伪代码向我们展示了OOP思想中的异常处理机制,可以看到,异常处理机制能够很好地帮助我们处理程序运行中可能遇到的问题、代码审计、问题追踪定位与复现,让开发者能够更加方便地解决问题。

0x02.Java的异常处理机制

作为现代化的面向对象程序设计语言,Java同样提供了一套类似的异常处理机制。

异常类(java.lang.Exception)

异常类(Exception)是由Java提供的最为基础的异常类,也是所有异常的父类,通常用来表示Checked Exception,也可以处理部分Runtime Error

Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error。

我们编写的Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外,故也不在本篇的讨论范围内。

异常类有两个主要的子类:IOException 类和 RuntimeException 类。

异常类的继承关系如下:

img

内置异常类

在java.lang包中定义了一些初始异常类,可以方便开发者对各类异常进行捕获

详见菜鸟教程-Java异常处理

异常的抛出与捕获

Java的异常捕获方法同大部分程序设计语言的异常捕获方法相同,使用关键字throwthrows抛出异常,trycatch进行异常的捕获,finally作为异常处理机制的补充

抛出异常

一个可能出现异常的方法可以使用throw/throws关键字抛出(多个)异常:

import java.io.*;
public class className
{
  public void function(elementType elements) throws Exception1//,Exception2,exception3...
  {
    // Method implementation
    throw new Exception1();
    /*
    * throw new Exception2();
    * throw new Exception3();
    * ...
    */
  }
  //Remainder of class definition
}

捕获异常

捕获异常需要用到关键字try/catch(finally),语法如下:

try
{
    //natural code but which may throws Exception
}
catch(ExceptionName1 exception_name1)
{
    //code dealing with Exception
}
/*
*
//selectable part
catch(ExceptionName2 exception_name2)
{
    //dealing with Exception
}
catch(ExceptionName3 exception_name3)
{
    //dealing with Exception
}
...
*/
finally//selectable, which will always be running
{
    //code 
}

异常类的内置方法

Exception类从Throwable类继承了一些用于处理异常的方法,方便开发者在捕获异常后获得异常的相关信息

常见方法如下:

  • printStackTrace():用于打印异常出现的路径,通常是输出到终端
  • getMessage() : 返回关于发生的异常的详细信息
  • toString() : 使用getMessage()的结果返回类的串级名字。
  • getCause() : 返回一个Throwable 对象代表异常原因。
Extra:输出异常日志到文件(log)

程序在运行时随时可能发生异常,但是维护人员与程序使用者不可能时刻盯着屏幕,过多的异常与过长的异常路径全部输出到终端难以记录,也使程序的可维护性降低

一个比较好的解决方案是使用自定义的MyLog类,将异常路径输出到日志(log)当中,方便开发者进行审计

具体代码如下:

/*
*
* Copyright(C) 2020 arttnba3. All rights reserved
*
*/
//file:MyLog.java
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyLog
{
    public static void printLog(Exception error)
    {
        //Transform the data of function printStackTrace() into a stream, then a String
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        error.printStackTrace(new PrintStream(byteArrayOutputStream));
        String errorInfo = byteArrayOutputStream.toString();
        //print into the log file
        File log = new File("log/"+new SimpleDateFormat("yyyy-MM-dd HH.mm.ss").format(new Date())+".log");
        try
        {
            log.createNewFile();
            DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(log));
            dataOutputStream.writeBytes(errorInfo);
            dataOutputStream.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public static void printLog(Exception error, String logPath)//customized log output path
    {
        //Transform the data of function printStackTrace() into a stream, then a String
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        error.printStackTrace(new PrintStream(byteArrayOutputStream));
        String errorInfo = byteArrayOutputStream.toString();
        //print into the log file
        File log = new File(logPath);
        try
        {
            log.createNewFile();
            DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(log));
            dataOutputStream.writeBytes(errorInfo);
            dataOutputStream.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

MyLog类的使用如下:

import MyLog;
...
//where Exception occur
try
{
    ...
}
catch(Exception e)
{
    MyLog.printLog(e);//print the log out to files
    //MyLog.printLog(e, logpath);//print the log to your customized path
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值