Java 异常知识点一篇没够再来一篇
Java 异常处理使用
前一章已经详细地讲解对应的基础例子, 但是并没有把使用方式全部写出来, 这一章我们来详细地把使用方法说一说。
基础使用,try catch 语句。这里可以参看上一篇文章。接下来说说多个异常的情况。
先创建两个继承自 Exception 的异常类, 等下要用, 分别是: ParamException 和 LogicException 。
public class ParamException extends Exception {
public ParamException() {
}
public ParamException(String message) {
super(message);
}
public ParamException(Throwable cause) {
super(cause);
}
public ParamException(String message, Throwable cause) {
super(message, cause);
}
public ParamException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
public class LogicException extends Exception {
public LogicException() {
}
public LogicException(String message) {
super(message);
}
public LogicException(Throwable cause) {
super(cause);
}
public LogicException(String message, Throwable cause) {
super(message, cause);
}
public LogicException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
抛出异常使用 throw 关键字, 使用方法如下:
throw new ParamException("参数错误,请验证您的参数是否正确!");
这里多说一句, 就是对于异常来说, 有两种情况, 一种是继承 RuntimeException 异常的, 另一种是继承非 RuntimeException 以及子类的。区别是是否需要显式地使用 throws 抛出异常。RuntimeException 异常不需要显式地抛出。
显式的继续往上抛出以上使用 throws 关键字。使用方法格式如下:
void test(String s) throws ParamException
这里如果是需要抛出异常, 没有捕获, 也没有往上抛出, 就会报错, 错误如下:
并且在抛出之后,在上层依然可以选择抛出和捕获, 代码能控制的最上层没有捕获的情况下, 还往上抛出, 就由 Java 虚拟机进行捕获并打印出对应的异常。例如:
public static void main(String[] args) throws ParamException
当然也可以直接捕获, 例如:
基础的用法就引申这么多, 接下来看看其他的使用方式。
多个 catch 语句
如果有多个异常的情况下, 就需要根据异常的从小到大进行捕获,或者就写最上层的 Exception 异常。 因为该异常是所有异常类的父类, 所以捕获它就不需要多个 catch 的情况了。 举例需要多个 catch 语句:
如果不想写多个 catch 就可以使用父类 Exception 进行捕获。
如果抛出异常,却没有捕获,或者没有写全, 就会抛出错误。错误信息如下:
多 catch 的优化
对于多个异常, 又不想写多个 catch 语句, 有没有办法呢, 答案是有的, 可以使用 “|” 来分割多个异常信息。 举例说明:
非常容易理解, 且符合规则,能一手抓住, 就不要下两次手。
异常中再抛出异常
除了上面简单的异常, 还会遇到异常中再抛出异常的。 大多数情况下这个问题出现在 IO 操作, 以及 SQL 操作, 需要关闭资源, 但是关闭资源有会出现关闭异常的问题, 需要关闭的已经关闭了。 或者需要打开的已经打开了。
finally
让我们先下一个例子, 然后再说 finally 的使用规则。
demo06.again("");
System.out.println("继续执行业务,查看我的输出。");
查看上面的代码, 发现, 在抛出异常的时候, 并没有执行第 6 行的代码。而是直接退出程序了。 如果说, 对于业务来说, 如果出现了异常不应该直接退出, 而是做一些善后的工作?或者说必须不管是否抛出异常,都要执行的代码。 这个时候, Java 异常体系中就可以使用关键字 finally 了。它的含义是, 不管是否抛出异常都将执行该代码。
上面的代码只是为了演示其用法, 并没有真实的意义, 使用一个真实的小例子来说一下。
该案例的是读取相同目录中 Demo01.java 文件的内容。 因为编写代码的时候都是使用 UTF-8 的格式。所以需要看你的系统默认是什么格式, 我这默认的是 GB18030 所以进行了转码。案例如下:
运行查看效果:
这里你将发现,使用了 finally 语法将没有关闭的 IO 操作进行关闭。任何资源的打开都需要关闭, 否则资源一直使用却不清理,总会把资源占满。 而影响程序的使用。
简化 try 语法 try-with-resources
对于 try-with-resources 是 Java 7 引入的语法结构。主要原因是为了使代码更加易读,更清晰的管理代码。
根据上面的一个例子, 可以改造成简化的语法。 代码如下:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Demo08 {
public static void main(String[] args) {
File file = new File("Demo01.java");
try (InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
BufferedReader reader = new BufferedReader(isr)) {
// 转换编码格式为 UTF-8 否则可能会有乱码
String tempString = null;
int line = 1;
// 循环读取文件, 当文件为 null 结束循环。
while ((tempString = reader.readLine()) != null) {
System.out.println("line " + line + ": " + tempString);
line++;
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行测试查看效果:
从代码上看, 首先代码量大量减少, 并且不需要关关闭的顺序, 程序会自动判断。 为什么能判断到, 主要是因为 Closeable 接口的原因, 如果想自动关闭, 必须实现接口 AutoCloseable。而 Closeable 继承了 AutoCloseable。 实现对应的唯一的方法:
public void close() throws IOException
只要实现该方法, 即可使用该语法。推荐后续都使用该语法, 以防你在写代码的时候, 忘记关闭必要的需要关闭的资源。
而 InputStreamReader 类同样继承了 Reader 抽象类,所以一样可以使用该简化的方式。
本来觉得上一篇异常足够了, 没想到又简单写写又写了一篇。这次应该把异常相关的内容写得差不多了吧?当然使用起来还要灵活应用。希望对你有所帮助。
关注, 点赞, 收藏。 感谢您的阅读。