概述
不管是大型网站、应用还是一个几十行的程序,运行时都会出现一些问题,有的问题比较严重可能导致服务器宕机,而有的问题,并不会导致服务器宕机,但是若是处理不当,很可能会产生数据库数据紊乱,从而发生未知的问题。
针对后一种问题,Java 使用了异常来正确处理这些问题。单独使用异常通常可以使错误处理代码简化。相比较而言,C 语言的异常处理并不属于语言本身的一部分,而是需要开发者们约定俗称一套机制,例如最常见的printf
函数,函数可能出现的错误情况均以返回值来区别,这种机制直接导致编写代码的时候有诸多与代码本身逻辑没有关系的判错代码。
Java 中的异常同样是一个对象,即将一个错误定义为一个对象,在运行到代码某处时若出现错误,则抛出相应的异常,使用throw
关键字来抛出一个异常,异常抛出后有两种解决方案:
- 一种是直接使用
try{}catch(){}
这样的结构来当场捕获处理 - 另一种是使用
throws
关键字直接抛给上层程序去处理
自定义异常与日志记录
自定义异常类,需要继承自现成的异常类,通常是继承自意思比较相近的异常类。
使用 java.util.logging
包下的logger
对象来输出日志。
//自定义异常类
class MyException extends Exception {
private static Logger logger = Logger.getLogger("MyException");
public MyException() {
StringWriter sw = new StringWriter();
//将异常所在的堆栈信息输出到 sw
printStackTrace(new PrintWriter(sw));
logger.severe(sw.toString());//记录一条 SEVERE 消息。
}
}
public class test {
public static void main(String[] args) {
try {
throw new MyException();
} catch(MyException e) {
System.err.println("catch----"+e);
}
}
}
/**Output:
三月 20, 2019 8:47:39 下午 MyException <init>
严重: MyException
at test.main(test.java:19)
catch----MyException
*/
异常作为一个对象,也可以自定义增加额外的构造器和成员变量,使用父类Throwable
中的getMessage()
方法可以产生更加详细的信息。
异常说明
针对自定义异常,其他客户端开发者通常只关心异常的名称以及产生异常的位置,因此异常的其他功能并不是很重要,Java 标准类库中的异常都是没有额外的变量。
如果有其他开发者使用你的程序,那么怎么确保他们知道你写的这个方法会产生何种异常呢?
前面说到可以通过throws
往上层调用的程序抛出异常,就是用在此处,通过强制使用throws
抛出当前方法中的异常,可以使得其他开发者不用阅读你的源码也能知道将要处理什么异常。
class myClass {
//在方法参数列表后面声明可能抛出的异常类型
public void f() throws Exception {
throw new Exception();
}
}
public class test {
public static void main(String [] args) {
myClass my = new myClass();
try {
my.f();// 在此处处理方法 f 抛出的异常
} catch(Exception e) {
e.printStackTrace();
}
}
}