目录
- 一、异常
- (1)异常分类
- (2)throw抛出异常
- (3)throws声明异常
- (4)捕获异常
- 二、带资源的try语句(try-with-resources)
- 三、保留原始异常细节
- 四、打印异常
- 五、总结
一、异常
(1)异常分类
Throwable
Error
Exception
IOException
ReflectiveOperationException
ParseException
......
RuntimeException
- 非受查异常:Error 和 RuntimeException(不需要声明)
- 受查异常:其他Exception(需要声明)
常见的RuntimeException
异常 | 说明 |
ArrayIndexOutOfBoundsException | 数组越界异常 |
NullPointerException | 空指针异常 |
ArithmeticException | 除零异常 |
(2)throw抛出异常
在方法内部
throw new NullPointerException();
throw new IOException();
注意:如果子类覆盖了超类中的一个方法,子类方法可以抛出更特定的异常,或不抛出异常;如果超类方法没有抛出受查异常,子类也不能抛出受查异常
空指针异常可使用Objects.requireNonNull (obj , “传递的对象值为null”);
(3)throws声明异常
将异常抛出,交给方法的调用者
一个方法必须声明所有可能抛出的受查异常,而非受查异常要么不可控制(Error),要么就应该避免发生(RuntimeException)
public void xxx() throws IOException{
}
(4)捕获异常
try {
A
B
}
catch (Exception e){
C
}
finally {
D
}
E
若A语句异常则顺序为:A->C->D->E(不再执行B)
若无异常则顺序为:A->B->D->E
若catch中异常有父子类关系,则子类异常必须写在上面
catch(子类 e){
}
catch(父类 e){
}
finally语句表示无论是否出现异常都会执行,try语句可以只有finally,而没有catch
try {
try {
throw new IOException("出错了");
}
finally {
System.out.println("资源释放");
}
}
catch (Exception e){
System.out.println(e);
}
二、带资源的try语句(try-with-resources)
上面的代码如果在try中的代码抛出了一个非 IOException异常,执行finally的方法时抛出了 IOException 异常。这种情况下,原始的异常将丢失,转而抛出 IOException 异常。而解决这种问题代码将变得极其繁琐
InputStream in = null;
Exception ex = null;
try{
try{
//code…..;
} catch (Exception e) {
ex = e;
throw e;
}
} finally {
try {
in.close();
} catch (Exception e) {
if(ex == null)
throw e;
}
}
在这里介绍带资源的try语句,将会完美解决这类问题。
try(Scanner in = new Scanner(new FileInputStream("a.txt"))) {
while(in.hasNext()) {
System.out.println(in.next());
}
}
可以指定多个资源:用 ;分隔
try(Scanner in = new Scanner(new FileInputStream("a.txt"));
PrintWriter out = new PrintWriter("b.txt")) {
while(in.hasNext()) {
out.println(in.next().toUpperCase());
}
}
当该语句被执行时,不管是否有异常被抛出,都会自动关闭资源,就好像使用了finally块一样
三、保留原始异常细节
我们对底层抛出的异常捕获后,抛出一个新的统一的异常,会让最原始的异常信息丢失,这样不利于排查问题。而采用如下包装技术,就不会丢失原始异常的细节。
不采用包装类:
class A
{
try
{
}
catch(AException a)
{
throw new BException();
}
}
...
class B
{
try
{
}
catch(BException b)
{
//无法知道是A导致的B
}
}
采用包装类:
class A
{
try
{
}
catch(AException a)
{
BException b = new BEexception();
b.initCause(a);
throw b;
}
}
...
class B
{
try
{
...
}
catch(BException b)
{
//得到导致B异常的原始异常
b.getCause();
}
}
四、打印异常
方法 | 说明 |
String getMessage() | 简短描述 |
String toString() | 详细描述 |
void printStackTrace() | 追溯打印到标准错误流 |
五、总结
早抛出,晚捕获