【Java基础 四】---异常处理
来源:互联网 发布:外国域名注册机构 编辑:程序博客网 时间:2024/06/17 06:52
异常的基本知识
异常的概念
要知道,异常指的都是运行时异常!编译错误一般指语法什么的错误,在运行之前IDE就会有提示。
上图中的代码就是数组下标越界
异常的分类
error是系统异常,例如当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。 程序处理不了。exception是可以处理的,runtime exception是一种经常出的错误,可以catch也可以不catch。而其它exception,=是必须得逮的exception,方法自己就自带的exception
Java中的异常分为两大类:
1.Checked Exception(非Runtime Exception)
2.Unchecked Exception(Runtime Exception)
运行时异常
RuntimeException类是Exception类的子类,它叫做运行时异常,Java中的所有运行时异常都会直接或者间接地继承自RuntimeException类。
非运行时异常
Java中凡是继承自Exception,而不继承自RuntimeException类的异常都是非运行时异常。对于非运行时异常(checked exception),必须要对其进行处理,否则无法通过编译。
处理方式有两种:
1.使用try..catch..finally进行捕获;
一个try后面可以跟多个catch,但不管多少个,最多只会有一个catch块被执行。
2.在产生异常的方法声明后面写上throws 某一个Exception类型,如throws Exception,将异常抛出到外面一层去。
对于运行时异常(runtime exception),可以对其进行处理,也可以不处理。推荐不对运行时异常进行处理。
处理异常
知道了上边异常的组成部分,我们针对其中需要处理的(非运行时异常)的两种处理方式。
Try…catch…finally
基本流程
在发现语句1出错,后边的语句不会执行,也就是说语句2不会被执行了,而是执行finally之后的 try catch之外的其它语句
public class Fileexception { public static void main(String[] args) { FileInputStream in = null; //一定要定义在try外边,记住作用域是在大括号之间 try { in = new FileInputStream("myfile.txt"); int b; b = in.read(); while (b != -1) { System.out.print((char) b); b = in.read(); } } catch (FileNotFoundException e) { //一定要先写FileNotFoundException,因为FileNotFoundException是IOException的子类,因为写catch是先小后大 e.printStackTrace(); } catch (IOException e) { System.out.println(e.getMessage()); } finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } }}
使用多重catch
很多情况下,由单个的代码段可能引起多个异常。处理这种情况,我们需要定义两个或者更多的catch子句,每个子句捕获一种类型的异常,当异常被引发时,每个catch子句被依次检查,第一个匹配异常类型的子句执行,当一个catch子句执行以后,其他的子句将被旁路。
顺序问题:先小后大,即先子类后父类
Java通过异常类描述异常类型。对于有多个catch子句的异常程序而言,应该尽量将捕获底层异常类的catch子句放在前面,同时尽量将捕获相对高层的异常类的catch子句放在后面。否则,捕获底层异常类的catch子句将可能会被屏蔽。例如:RuntimeException异常类包括运行时各种常见的异常,ArithmeticException类和ArrayIndexOutOfBoundsException类都是它的子类。因此,RuntimeException异常类的catch子句应该放在最后面,否则可能会屏蔽其后的特定异常处理或引起编译错误。
try ,catch,finally组合情况
亲测后有以下几条规则
1,try+catch后有没有finally无所谓
try+catch+finally可以使用
try+catch可以使用
2,try必不可少
try+finally,try+catch都可以
3,三个变量不能单独使用任何一个,即使是try如果不加catch也必须有finally(声明了异常就一定要处理,不管是在catch还是finally中)
总结就是必须有try和(catch,finally,catch+finally)三个组合中的一种
return的执行时机
通用场景
1、不管有没有出现异常,finally块中代码都会执行;
finally里没有return的场景,但try或catch里有
2、当try和catch中有return时,finally里没有return,finally仍然会执行,因此在return返回时不是直接返回变量的值,而是复制一份,然后返回,因此,对于基本类型的,finally的改变没有影响,对于引用类型的就有影响了
package test;/ * @author 田茂林 * @data 2017年9月6日 下午9:46:42 */public class TestFinally{ public static int testFinally1(){ //基本类型的 int result =1; try { result = 2; return result; } catch (Exception e) { return 0; }finally{ result =3; System.out.println("execult Finally1"); } } public static StringBuffer testFinally2(){ //引用类型的 StringBuffer s = new StringBuffer("Hello"); try { return s; } catch (Exception e) { return null; }finally{ s.append("world"); System.out.println("execult Finally2"); } } public static void main(String[] args) { int result1 = testFinally1(); System.out.println(result1); StringBuffer result2 = testFinally2(); System.out.println(result2); }}
输出结果
execult Finally12execult Finally2Helloworld
finally里有return的情况
3、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。返回值是finally里的return返回的值
注意,如果是return i++返回i的值,return ++i返回的是++i的值,也就是永远返回当前值
package test;/** * @author 田茂林 * @data 2017年9月6日 下午9:46:42 */public class TestFinally { @SuppressWarnings("finally") public static int testFinally() { // 基本类型的 int i = 1; try { ++i; return i; } catch (Exception e) { } finally { return i++; // 2 // return ++i; //3 } } public static void main(String[] args) { int result1 = testFinally(); System.out.println(result1); }}
总结:
对于finally块中没有return语句的情况,方法在返回之前会先将返回值保存在局部变量表中的某个slot中,然后执行finally块中的语句,之后再将保存在局部变量表中某个slot中的数据放入操作数栈的栈顶并进行返回,因此对于基本数据类型而言,若在finally块中改变其值,并不会影响最后return的值。
而对于finally块中包含了return语句的情况,则在try块中的return执行之前,会先goto到finally块中,而在goto之前并不会对try块中要返回的值进行保护,而是直接去执行finally块中的语句,并最终执行finally块中的return语句,而忽略try块中的return语句,因此最终返回的值是在finally块中改变之后的值。
catch块和finally块里可以抛出异常么
可以但是需要加try,catch环绕,或者直接从方法上声明抛出
throws和throw
public class ManangeException { public static void main(String[] args) { //直到抛到main方法里,不要再main方法里写throws,main方法会打印堆栈信息,但最好在main方法里处理异常 ManangeException m=new ManangeException(); try { m.f2(); } catch (IOException e) { System.out.println("没有找到该文件"); } } public void f() throws FileNotFoundException,IOException{ //不处理只抛出 FileInputStream in = null; in = new FileInputStream("myfile.txt"); int b; b = in.read(); while (b != -1) { System.out.print((char) b); b = in.read(); } } public void f2() throws IOException{ //一级一级往外抛 f(); } ============================================================ public void m(int i) throws ArithmeticException{ if(i==0) throw new ArithmeticException("被除数为0"); //手动抛出异常 } }
main调用了f2()——f2()调用了f()——f()抛出了异常
自定义异常
class MyException extends Exception { private int id; public MyException(String message, int id) { super(message); this.id = id; } public int getId() { return id; }}public class TestMyException { public void regist(int num) throws MyException{ if(num<0) throw new MyException("不合法的人数", 1); //这要是异常抛出,则不会打印下边的那句话 System.out.println(num); } public void m(int i){ try { regist(i); //方法体里边不能再写方法,但是可以直接调用就好 } catch (MyException e) { System.out.println("出现故障"); } } public static void main(String[] args) { TestMyException t=new TestMyException(); t.m(1); }}
常见异常类
图片来自http://www.cnblogs.com/Qian123/p/5715402.html#_label2
- 【Java基础 四】---异常处理
- 四 Java 异常处理
- 四、JAVA异常处理
- java基础(四)之java浅析异常处理机制
- JAVA基础笔记四——异常处理
- java基础 ---异常处理
- Java基础:异常处理
- Java基础 异常处理
- Java基础-异常处理
- Java基础:异常处理
- java异常处理基础
- Java基础--异常处理
- Java基础--异常处理
- 【Java基础】--异常处理
- Java基础-异常处理
- Java基础--异常处理
- Java异常处理基础
- JAVA基础:异常处理
- php 连接mysql数据库,查询、插入、更新、删除功能
- 【面向对象设计原则】之 单一职责原则(SRP)
- SpringSecurity下做POST测试以及传递实体
- react-native 学习 ----- React Navigation
- MongoDB学习1
- 【Java基础 四】---异常处理
- 通过ThreadLocal和Filter实现请求上下文【旧】
- android控件09---TabHost
- Java反射机制动态代理
- struts2 ActionMethod DMI 动态方法调用
- Linux上如何查看某个进程的线程
- /mnt/backup/android-x86-7.1-rc1-mptcp/kernel/arch/x86/configs/android-x86_64_defconfig
- 343. Integer Break
- 运行别人写好的 electron 项目