在复习java的过程中碰到了异常,关于异常虽然自己常常会用到,但是其中一些问题一直没有搞清楚,今天来把它捋一遍。
异常介绍
首先异常分为两种:Error 和 Exception,就是程序的错误和异常。
Error英译就是错误,是JVM本身的错误,我们不需要在意这个Error,而本篇文章着重于Exception。
Exception英译就是异常,它与Error都继承于Throwable,这个异常是我们开发人员需要去捕获的错误。而关于Exception又有两种异常一种为:RuntimeException字面意思就是运行时异常,而除了RuntimeException以外的异常全是检查异常。
异常的处理
关于异常的处理有几种处理形式,我在网上看了五花八门的分类,有一种说法比较好:分为主动和不主动的。
主动的就是捕捉异常处理,通过try-catch去捕捉。
值得一提的是,关于try-catch你还可以有另外一种写法,也就是try-with-resources,写法为try(){}catch{}finally{},下面会有解释这个写法的用途。
代码示例:
以String数组坐标越位异常为例
* 异常的处理
*
* @author Vision
*
*/
public class C extends B {
public static void main(String[] args) {
try {
new C().hello();
} catch (Exception e) {
// e.printStackTrace();
System.out.println("String数组越位啦");
} finally {
System.out.println("需要处理异常");
}
}
void hello() {
String[] strings = new String[0];
System.out.println(strings[0]);
}
}
代码分析:try{}包裹的代码块就是咱们要分析的语句,如果捕捉到了异常则是在cath{}中处理,而finally{}中最后是一定会执行的。e.printStackTrace();这个是程序会告诉你哪里报错。
运行结果:
关于try-with-resources的代码如下:
public void outPut(String path) {
// 文件字节输出流(内存写到数据源)
// 通过try-with-resources隐式地实现了AutoColoseable接口,自动关闭了资源
try (FileOutputStream fileOutputStream = new FileOutputStream(new File(path))) {
fileOutputStream.write('a');
fileOutputStream.write('c');
String string = "abcddfdasfas";
byte[] bytes = string.getBytes();
fileOutputStream.write(bytes);
} catch (Exception e) {
e.printStackTrace();
}
}
代码分析:在IO操作中我们通常需要关闭流的,但是通过这种方式可以自动对流进行关闭,但是请注意你的jdk版本(需要1.7)。
而被动的异常处理就是throw和throws。throws是声明异常,它通过声明的方式抛出各种异常类,如果有方法需要声明异常那么调用它的话也需要声明异常,就是一层一层往上抛,最后算是交给JVM解决问题了。
而throw则是自己手动抛出一个实例化的异常对象,算是抛出异常了。可以配合try-catch和throws使用的。而且throw和throws一般是成对出现的,通过配合不仅可以抛出异常,有的时候算是一种特殊传参手段。代码跟下面自定义异常的写在一起了。
自定义异常
之前提到了可以通过throw手动的抛出异常,在日常开发中除了jdk提供的这些异常以外,我们也会自己需要定义异常,用于提示内部人员开发出现了异常。
代码如下:
/**
* 测试自定义异常
*
* @author Vision
*
*/
class MyException extends RuntimeException {
MyException(String errorMsg) {
super(errorMsg);
}
}
public class ExTest {
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
String next = scanner.next();
if (next.equals("hh")) {
throw new MyException("hh是不允许的!");
}
}
}
运行结果的截图
这里由于MyException是继承于RuntimeException的所以方法不需要加throws,如果我们将MyException改为继承于Exception,情况就不一样了。
好吧,开发工具都不允许我这样干。。。
我们就需要throws声明和throw成对出现了,我当时在思考Exception不是RuntimeException的父类吗,为什么会这样呢,现在看很明显电脑是不认的,我们就是要声明的。
常见的异常
写四个常见的运行异常和四个常见的非运行异常:
运行异常:
NullPointerException
IndexOutOfBoundsException
ClassCastException
ClassNotFoundException
非运行异常:
IOException
SQLException
DateFormatException
InterruptException
总结
虽然异常处理不是万能的,但是没有异常处理是万万不能的。