异常处理(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用着属实恼火
现代的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思想中的异常处理机制,可以看到,异常处理机制能够很好地帮助我们处理程序运行中可能遇到的问题、代码审计、问题追踪定位与复现,让开发者能够更加方便地解决问题。
作为现代化的面向对象程序设计语言,Java同样提供了一套类似的异常处理机制。
异常类(Exception)是由Java提供的最为基础的异常类,也是所有异常的父类,通常用来表示Checked Exception,也可以处理部分Runtime Error。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error。
我们编写的Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外,故也不在本篇的讨论范围内。
异常类有两个主要的子类:IOException 类和 RuntimeException 类。
异常类的继承关系如下:
在java.lang包中定义了一些初始异常类,可以方便开发者对各类异常进行捕获
详见菜鸟教程-Java异常处理
Java的异常捕获方法同大部分程序设计语言的异常捕获方法相同,使用关键字throw、throws抛出异常,try、catch进行异常的捕获,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类继承了一些用于处理异常的方法,方便开发者在捕获异常后获得异常的相关信息
常见方法如下:
程序在运行时随时可能发生异常,但是维护人员与程序使用者不可能时刻盯着屏幕,过多的异常与过长的异常路径全部输出到终端难以记录,也使程序的可维护性降低
一个比较好的解决方案是使用自定义的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
}