目录

  • 一、异常
  • (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();

java 抛出异常捕获后 想打印打错行 java异常抛出和捕获_子类


注意:如果子类覆盖了超类中的一个方法,子类方法可以抛出更特定的异常,或不抛出异常;如果超类方法没有抛出受查异常,子类也不能抛出受查异常

空指针异常可使用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()

追溯打印到标准错误流

五、总结

早抛出,晚捕获