java异常和错误共有的超类为Throwable
https://www.cnblogs.com/AbelZone/p/10049997.html
-
定义:java提供的一种识别及响应错误的一致性机制
-
涉及到的关键:try; catch;finally;throw;throws
-
分类:主要分为两大类:
-
编译时异常(Exception子类除去RuntimeException以外都是编译时异常):可查异常(编译器要检查的异常,可以提前预知的异常,编译器不通过不能运行的异常)
-
可以通过try......catch方法通过编译器的检查,或者通过泛型骗过编译器的检查,最终在JVM中运行打印异常)例子如下(idea中的编译器不能骗过,java8的能骗过):
-
-
- 运行时异常(RuntimeException):不可查异常(编译器不会检查的异常,发生的可能性比较低的异常,一般是由程序逻辑问题造成的异常)
- 针对之前上课听到的所有异常都发生在程序运行的时候的解释:
- 编译器也能打印异常,这个是编译器行为而不是JVM行为,比如利用泛型骗过编译器,则编译器通过,JVM运行结果是
- 如果将RuntimeException改成IOException则编译器检查出语法异常,编译器打印异常为:
- 综上所述:利用try...catch等方法在编译器通过之后,异常的发生都在运行阶段是没有问题的。
- 编译器也能打印异常,这个是编译器行为而不是JVM行为,比如利用泛型骗过编译器,则编译器通过,JVM运行结果是
- 面试题
- finally和finalize和final的区别:在try结构中,无论如何都会执行finally,所以finally的方法体中适合用作释放资源和后续需要处理的代码
- try{}catch{}finally{}语句结构中如果在try中出现return时,不同情况的分析,表明try中的return已经执行但是因为finally不能立刻结束,所以只进行了i++,最后在finally中执行了return
public static int testReturn(){
int i = 0;
try {
i++;
System.out.println("try");
return ++i;//这里也执行i++,但是没有进行return
}finally {
System.out.println("finally");
return ++i;//最后在这里结束返回3
}
//return ++i; //因为try中有return所以这里不可能被执行到。
}
上述方法结论验证了finally无论如何都会执行,return都不能阻止。
public static int testReturn2(){
int i = 0;
try {
i++;
System.out.println("try");
return ++i;
//这里先执行i++,但是没有立刻进行return,
// 等finally中的语句执行完毕在执行返回,
// 但是因为程序必须由上至下执行随意只能返回2
}finally {
System.out.println("finally");
++i;//finally中已经语句已经执行
}
}
上述方法结论验证了finally无论如何都会执行,同时遵守了编程语言亘古不变的道理语句是自上而下执行的
- 异常定义
public class MyselfException extends IOException {
public MyselfException(){super();}
public MyselfException(String message){
super(message);
}
}
public <E extends Throwable> void throwException01(E t) throws E {
throw (E)t;//正确的泛型方法
}
- 注意事项
- 两小一大原则,在编译时异常的条件下,当含有throw的方法重写时,子类的异常必须小于等于父类(子类抛出的异常必须是父类抛出异常的子类或者和父类抛出的异常相同)
- 异常抓取catch的时候只能是try中的产生的异常类或者是其父类(子类则抓不到),下面这个列子能抓到,是因为抛出对象a本质是Sneeze类,这里发生了向上转型。
class Annoyance extends Exception {
}
class Sneeze extends Annoyance {
}
class Human {
public static void main(String[] args)
throws Exception {
try {
try {
throw new Sneeze();
} catch ( Annoyance a ) {
System.out.println("Caught Annoyance");
throw a ;
}
// throw new Annoyance();
} catch ( Sneeze s ) {//这里能抓住异常是因为存在Sneeze异常
System.out.println("Caught Sneeze");
return ;
} finally {
System.out.println("Hello World!");
}
}
}
/*
Caught Annoyance
Caught Sneeze(这个能被抓住是因为这个对应的try是外面那个里面有两个异常对象)
Hello World!
*/
- 异常方法处理:
public static void main(String[] args) { //自动关闭了Scanner开启的流 try(Scanner in = new Scanner(new FileInputStream ("D:\\IdeaProjects\\basic.code\\object"),"UTF-8")){ ArrayList bList = new ArrayList<>(); while(in.hasNext()){ bList.add(in.next()); } String str = bList.toString(); System.out.println(str); }catch(IOException e){ e.printStackTrace(); } }
//验证了可以同时关闭多个资源,且相互不影响 public class Test04Exception { public static void main(String[] args) { try(MyImplementAutoCloseable a = new MyImplementAutoCloseable(); My2ImplementAutoCloseable b = new My2ImplementAutoCloseable()){ a.doSome(); b.doOther(); }catch(IOException e){ e.printStackTrace(); } } } class MyImplementAutoCloseable implements AutoCloseable { public void doSome(){ System.out.println("dosome"); } @Override public void close() throws IOException { System.out.println("doSome资源已经关闭"); } } class My2ImplementAutoCloseable implements AutoCloseable { public void doOther(){ System.out.println("doOther"); } @Override public void close() throws ClassCastException { System.out.println("doOther资源已经关闭"); } } /*输出结果是 dosome doOther doOther资源已经关闭 doSome资源已经关闭 */
//使用try-with-resource语句是关闭所有资源之后才捕捉异常的,这保证把所有正常的资源全部关闭 public class Test04Exception { public static void main(String[] args) { try(MyImplementAutoCloseable a = new MyImplementAutoCloseable(); My2ImplementAutoCloseable b = new My2ImplementAutoCloseable()){ // a.doSome(); // b.doOther(); }catch(IOException e){ e.printStackTrace();//这个最后显示是因为这里调用printStream的时候锁了一定时间,导致一段时间后才打印。 System.out.println(e.getMessage()); Throwable[] throwArray = e.getSuppressed();//获取被抑制的异常Throwable数组 System.out.println(throwArray[0].getMessage()); } } } class MyImplementAutoCloseable implements AutoCloseable { public void doSome(){ //throw new IOException("doSome扔出的异常"); System.out.println("dosome"); } @Override public void close() throws IOException { System.out.println("MyImplementAutoCloseable资源已经关闭"); throw new IOException("MyImplementAutoCloseable资源关闭的时候扔出的异常"); } } class My2ImplementAutoCloseable implements AutoCloseable { public void doOther(){ System.out.println("doOther"); } @Override public void close() throws IOException { System.out.println("My2ImplementAutoCloseable资源已经关闭"); throw new IOException("My2ImplementAutoCloseable资源关闭的扔出的异常"); } } /* My2ImplementAutoCloseable资源已经关闭 MyImplementAutoCloseable资源已经关闭 My2ImplementAutoCloseable资源关闭的扔出的异常 MyImplementAutoCloseable资源关闭的时候扔出的异常 java.io.IOException: My2ImplementAutoCloseable资源关闭的扔出的异常 at chl.java.TestException.My2ImplementAutoCloseable.close(Test04Exception.java:38) at chl.java.TestException.Test04Exception.main(Test04Exception.java:11) Suppressed: java.io.IOException: MyImplementAutoCloseable资源关闭的时候扔出的异常 at chl.java.TestException.MyImplementAutoCloseable.close(Test04Exception.java:28) ... 1 more */
- throws抛给上一级
- try...catch...finally自己处理
- try-with-resources这是JDK7的新特性,并且在JDK9的时候进行更新(更新后可以直接在try中使用常量资源,不需要在try中声明新的变量)。主要作用就是确保每个资源在语句结束时关闭,避免了在finally中的close方法可能抛出的IOEexception覆盖原始异常。使用try-with-resource语句是关闭所有资源之后才捕捉异常的,这保证把所有正常的资源全部关闭。
- Throwable的另一个子类是Error:比如StackOverflow等,当出现错误时,JVM停止运行,程序员不应该对Error类做处理。