1.java异常处理结构
【图片来源菜鸟教程】
Throwable类是Java所有错误和异常的父类。
1. 基本概念
- 检查异常 除了Error 和 RuntimeException的其它异常
这类异常一般在写程序的过程中 会强制要求做处理:可以直接throws抛出或try-catch语句捕获
- 非检查异常 Error 和 RuntimeException 以及他们的子类
通俗得理解就是:这些异常,和自己写的代码逻辑有很大关系,这类异常在编译得时候一般能通过,在程序运行过程中会抛出这些异常 如IndexOutOfBoundsException NullPointerException
2. 异常处理方法
- 2.1 异常关键字 try、catch、finally、throw、throws
try-catch-finally: 将可能要出现异常的代码放入try中,catch 捕获 try 中的异常,并处理,不管有没有异常,finally中的代码都会执行。(finally不是必须)
throw: 一般是语句抛出一个异常
throws:一般是方法抛出一个异常
- 2.2 异常分类 2.2.1 捕获异常
利用try-catch捕获异常 将可能抛出异常的代码放在try中 用catch去捕获这些异常
2.2.2 声明异常
throws在方法后面声明异常(表示该方法可能会产生异常)
若声明的是受检查的异常 则在调用该方法时也要声明异常(一般开发工具会自动提示两种方法处理:继续throws或try-catch)
若声明的时非检查异常(指RuntimeException 以及他们的子类) 则不用做强制处理 可以不用声明
throw是在方法里面声明异常 一般是手动抛出,并且可以抛出更为明确的异常
2.2.3 自定义异常
一般自定义异常会继承Exception或RuntimeException类 但具体继承哪一个类呢 还是要视情况而定
若继承受检查的异常,会与方法耦合,若不抛异常就要try-catch 操作不够灵活
若继承RuntimeException 就相对上面的就简洁多了
2.举例
例子:下载本地文件
- 当new FileInputStream("") 会提示抛出异常
进入看源码 可以发现FileInputStream声明了一个异常(FileNotFoundException),FileNotFoundException是检查异常,在new的时候要抛出
- 当关闭流的时候也要抛出异常 若直接throws后
当throws后 说明前面两个异常的父类是IOException
- 自定义异常
//这就是自己自定义异常 并将错误码传出
public CustomizeException(String code, String message) {
super(message);
this.code = code;
}
public CustomizeException() {super();}
public CustomizeException(String message) {super(message);}
public CustomizeException(String message, Throwable cause) { super(message, cause);}
public CustomizeException(Throwable cause) { super(cause);}
public String getCode() {
return code;
}
}
- 抛出自己写的异常
6.整体代码:
//下载本地文件
public static void downloadFile(String filePath,HttpServletResponse response) throws IOException {
File file = new File(filePath);
if (file.exists()){
//若文件不存在 我可以抛出一个自己定义的异常
throw new CustomizeException("0001","该文件不存在,请重写上传文件");
}
FileInputStream inputStream = new FileInputStream(file);
String fileName = "人月神话";
response.setHeader("content-type","application/octet-stream");
response.setContentType("application/octet-stream");
//使下载的文件名正常显示中文
response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName, "UTF-8"));
byte[] buffer = new byte[1024];
try {
OutputStream outputStream = response.getOutputStream();
int i = inputStream.read(buffer);
while (i != -1){
outputStream.write(buffer,0,i);
i = inputStream.read(buffer);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
inputStream.close();
}
}
3.查看java API源码
Throwable
API解释: Throwable类是Java语言中所有错误和异常的超类。只有作为该类(或其子类之一)实例的对象才会被Java虚拟机(Java Virtual Machine)抛出,或者可以由Java throw语句抛出。类似地,只有这个类或它的一个子类可以成为catch子句中的实参类型。为了在编译时检查异常,Throwable和任何不是RuntimeException或Error子类的Throwable子类都被视为已检查异常。
Error
API给出的解释:
Error是Throwable的一个子类,它表示合理的应用程序不应该试图捕获的严重问题。大多数这样的错误都是异常情况。ThreadDeath错误虽然是一个“正常的”条件,但也是error的一个子类,因为大多数应用程序不应该试图捕获它。 方法不需要在其throws子句中声明任何可能在方法执行期间抛出但未捕获的Error子类,因为这些错误是不应该发生的异常情况。也就是说,Error及其子类被视为未经检查的异常,以便在编译时检查异常。
Exception
API给出的解释:
Exception类及其子类是Throwable的一种形式,它指示合理的应用程序可能希望捕获的条件。 Exception类和任何不是RuntimeException子类的子类都是检查异常。如果已检查异常可以在方法或构造函数的执行中抛出并传播到方法或构造函数边界之外,则需要在方法或构造函数的抛出子句中声明。
4.总结
在平时的编码中经常会用到异常处理机制 有些时候直接可以利用throws去把异常抛出,有些时候要用try-catch-finally去捕获异常,有些时候需要利用throw手动抛出异常,如关于流的关闭打开一般在try-catch-finally中更好,有一些异常需要明确的指出 则可以手动抛出,总之各有各的应用场景。这次对异常做了一个整体的梳理 也让我对java异常处理有进一步了解了,若有什么问题建议 欢迎及时指正!