提及异常,我就想起了Bug,也就是常说的信春哥,无Bug,什么是Bug呢?我理解的Bug就是没有按照本身原先假想的逻辑去执行,这其中包括了两个方面,一方面是代码语法问题,一方面是逻辑问题,就好比正常逻辑买了东西要付款,可是买家买了东西却没有付款,直接拿东西走了,这是逻辑问题,或者是原本数组存储3个元素,你却存了4个,这时候也出现了Bug,程序报错了,这种Bug就是异常。
异常也是Java类的一种,用new建立对象,他们的结构是这样的:java
Throwable程序员
error面试
Exception编程
恩,就是这样,异常分为错误和异常,感受有点绕口,但就是这样,像error这种错误是在编译期间就会报出来的,若是你使用的是IDE,因此咱们只须要关注Exception异常就能够了。数组
获取和处理异常可能就是异常的所有,咱们的一个原则就是:学习
发生异常就得让程序员知道this
怎么获取异常呢?Java给出了try关键字用来解决,咱们只须要将可能出现异常的代码放在try中就能够了,就像这样:日志
try{ ... }
java给出了尽可能优雅的解决方案来处理异常,它不但愿处理异常的代码和自己的业务代码有过多的混合,获取到异常就该处理异常,这时候就应该这样写了:code
try{ ... }catch(Type1 type1){ ... }catch(Type2 type2){ ... }
catch中的type表明了在try中可能出现的异常类型对象
catch如何匹配异常?
按顺序从第一个到最后一个,若是发现异常匹配,就中止匹配,和switch模式不同
基类包含子类异常,若是第一个是Exception,那么后面的都不用匹配了
那么catch中怎么处理这个异常呢?
不做处理(会出现“吞食”)
打印到控制台
写入日志
继续向上抛
在try块中抛出异常,咱们在catch中会匹配到相应的异常类型,这时候咱们就会拿到对应的异常对象的引用,咱们调用throwalbe的方法用于处理:
public class ExceptionMethods { public static void main(String[] args) { try { throw new Exception("My Exception"); } catch (Exception e) { System.out.println("Caught Exception"); System.out.println(e.getMessage()); System.out.println(e.getLocalizedMessage()); System.out.println(e); System.out.println(e.toString()); e.printStackTrace(); e.printStackTrace(System.out); } } }
咱们通常使用e.printStackTrace();打出异常栈信息便可
或者是写入Log,使用logger.error
每一个人处理处理异常的方式可能不尽相同
咱们除了可使用try来捕获异常,咱们也能够将这个异常抛出去,咱们能够把异常比做如今这种制度,地球村出了点问题,村长衡量了一下,以为这事情本身处理不了,就交给乡长了,这种把问题交给上层或者是Java编程思想中说的跳出当前环境,交给一个更大的环境去处理,这也是Java异常处理的一种思路。
if(t == null) throw new NullPointerException();
其实异常最重要的就是异常的名称,如今Java正在扩充异常的种类,可是不少异常可能不是咱们想要的,那么咱们就能够自定义异常:
class SystemErrException extends Exception{ }
这就是一个异常类,咱们继承了Exception,这个SysteErrException就能够用于咱们处理异常的时候了,固然咱们能够给他加点参数:
class SystemErrException extends Exception{ public SystemErrException(){ } public SystemErrException (String message){ super(message); } }
或者是这样:
class SystemErrException extends Exception{ private int i; public SystemErrException(){ } public SystemErrException (String message){ super(message); } public SystemErrException (String message, int i){ super(message); this.i = i; } }
这只不过是多加了几个参数,可是这些通常是没什么必要的。
说到这,就得说另外一个关键字throws,看清楚,不是throw,而是throws,这可能也是面试新手的时候会问的一个问题,throws是异常中的一个申明,在IO学习中会很是常见,它是一个声明,编译器检查到说你这段代码可能会发生什么异常,你要声明一下,这时候你就要在方法上声明:
public void inputFile() throws IOException{ .... }
finally用处就和他的意思相符,表示最终的含义,也就是finally里面的代码必定会获得执行:
案例一
public class FinallyException { static int count = 0; public static void main(String[] args) { while (true){ try { if (count++ == 0){ throw new ThreeException(); } System.out.println("no Exception"); }catch (ThreeException e){ System.out.println("ThreeException"); }finally { System.out.println("in finally cause"); if(count == 2) break; } } } } class ThreeException extends Exception{ }
执行结果:
ThreeException in finally cause no Exception in finally cause
案例二:return案例
public class MultipleReturns { public static void f(int i){ System.out.println("start......."); try { System.out.println("1"); if(i == 1) return; System.out.println("2"); if (i == 2) return; System.out.println("3"); if(i == 3) return; System.out.println("else"); return; }finally { System.out.println("end"); } } public static void main(String[] args) { for (int i = 1; i<4; i++){ f(i); } } }
执行结果:
start....... 1 end start....... 1 2 end start....... 1 2 3 end
咱们可能遇到这种状况,打开一个文件,读取文件,关闭文件,正常逻辑是这样的,可是这样会有几个问题:
在打开文件的过程当中出现异常,可是还要关闭文件
就像这样:
try{ A a = new A(); ... }catch(){ ... }finally{ a.close(); }
A在建立过程当中会出现异常,可是仍是会执行a的方法,好比关闭文件
因此咱们应该这么作:
try{ A a = new A(); try{ ... }finally{ a.close(); } }catch(){ ... }
通常报错都会报一大堆错误,你们无从看起,其实异常报错也是有规律的,这就是栈结构,先进后出,举个栗子:
public class WhoCalled { static void f() { try { throw new Exception(); } catch (Exception e) { for (StackTraceElement ste : e.getStackTrace()){ System.out.println(ste.getMethodName()); } } } static void g(){ f(); } static void h(){ g(); } public static void main(String[] args) { f(); System.out.println("---------------------------"); g(); System.out.println("---------------------------"); h(); System.out.println("---------------------------"); } }
运行结果:
f main --------------------------- f g main --------------------------- f g h main ---------------------------
能够看到异常信息都是从内到外的,按个人理解查看异常的时候要从第一条异常信息看起,由于那是异常发生的源头。
异常总的来讲仍是很重要的,也是保障程序健壮性很重要的一栏,而且能够达到立竿见影的效果,这里只是基本总结了异常的一些常见问题,不少还得在本身运用的过程当中去探索。