java-异常处理2
一 编译时异常和运行时异常的区别
java认为如果你的程序有问题,你应该让调用者知道.
例如:面包,长毛了.用户去买了,用户可能会挂 .应该在面包上贴上标签(异常).
java
如果在函数内抛出Exception//编译失败,因为编译器在检查语法时发生了错误。
该程序已经出现问题,Java认为这个程序本身存在隐患,
需要捕获或者声明出来(你要么把问题处理,要么把问题标识出来让调用知道)
1.1 抛RuntimeException不要捕获,不声明?
不是功能本身发生的异常,而是因为比如调用者传递参数错误而导致功能运行失败。(如数组下标越界)
这时也是问题,需要通过异常来体现,但是这个异常不要声明出来的。
声明的目的是为了让调用者进行处理。
不声明的目的是不让调用者进行处理,就是为了让程序停止,让调用者看到现象,并进行代码的修正。★★★★★
1.2异常分两种
1,编译时异常:编译器会检测的异常。
2,运行时异常:编译器不会检测的异常。不需要声明。声明也可以,如果声明了,无外乎就是让调用者给出处理方式。常见的异常
- ArrayIndexOutOfBoundsException
- IllegalArgumentException
- NullPointerException
- ClassCastException
二 异常的声明和捕获
2.1 声明和捕获
声明:将问题标识出来,报告给调用者。
如果函数内通过throw抛出了编译时异常,而捕获,那么必须通过throws进行声明,让调用者去处理。
捕获:Java中对异常有针对性的语句进行捕获。
语句:
try { //需要被检测的语句。 } catch(异常类 变量)//参数。 { //异常的处理语句。 } finally { //一定会被执行的语句。 } */
1.1.1声明 如果定义功能时有问题发生需要报告给调用者。可以通过在函数上使用throws关键字进行声明。
class Demo { void show(int x)throws Exception { if(x>0) throw new Exception(); else System.out.println("show run"); } } class ExceptionDemo7 { public static void main(String[] args) throws Exception//throws Exception//在调用者上继续声明。 { Demo d = new Demo(); d.show(1);//当调用了声明异常的方法时,必须有处理方式。要么捕获,要么声明。 } }
结果
1.1.2 捕获:Java中对异常有针对性的语句进行捕获。
try { //需要被检测的语句。 } catch(异常类 变量)//参数。 { //异常的处理语句。 } finally { //一定会被执行的语句。 } */
测试
package test; public class Test { public static void main(String[] args) { Demo d = new Demo(); try { d.show(1); } catch (Exception e) { System.out.println("异常发生了"); }//当调用了声明异常的方法时,必须有处理方式。要么捕获,要么声明。
System.out.println("Hello World!");
} } class Demo { void show(int x)throws Exception { if(x>0) throw new Exception(); else System.out.println("show run"); } }
结果
注意:上面的结果 hello world 不会运行,而用捕获时,hello world 运行了
2.2 异常捕获图解
2.3 声明捕获的应用
package test; public class Test { public static void main(String[] args) { try { Person p = new Person("xiaoming",-20); System.out.println(p); } catch (NoAgeException ex) { System.out.println("异常啦"); } } } class NoAgeException extends RuntimeException { /* 为什么要定义构造函数,因为看到Java中的异常描述类中有提供对问题对象的初始化方法。 */ NoAgeException() { super(); } NoAgeException(String message) { super(message);// 如果自定义异常需要异常信息,可以通过调用父类的带有字符串参数的构造函数即可。 } } class Person { private String name; private int age; Person(String name,int age)//throws NoAgeException { //加入逻辑判断。 if(age<0 || age>200) { throw new NoAgeException(age+",年龄数值非法"); } this.name = name; this.age = age; } //定义Person对象对应的字符串表现形式。覆盖Object中的toString方法。 public String toString() { return "Person[name="+name+",age="+age+"]"; } }
结果
构造函数到底抛出这个NoAgeException是继承Exception呢?还是继承RuntimeException呢?@@@
继承Exception,必须要throws声明,一声明就告知调用者进行捕获,一旦问题处理了调用者的程序会继续执行。
但是如果使用到了Person对象的数据,导致都失败的。
继承RuntimeExcpetion(用的多),不需要throws声明的,这时调用是不可能编写捕获代码的,因为调用根本就不知道有问题。
一旦发生NoAgeException,调用者程序会停掉,并有jvm将信息显示到屏幕,让调用者看到问题,修正代码
三 运行时异常的应用@
/* 描述长方形, 属性:长和宽。 行为:获取面积。 考虑健壮性问题。 万一长和宽的数值非法。 描述问题,将问题封装成对象,用异常的方式来表示。 */ /* 不知道要继承编译时异常还是运行时异常。 */ class NoValueException extends RuntimeException { NoValueException() { super(); } NoValueException(String message) { super(message); } } class Rec { private int length; private int width; Rec(int length,int width) { if(length<=0 ||width<=0) { //抛出异常,但是不用声明,不需要调用者处理。就需要一旦问题发生让调用者端停止,让其修改代码。 throw new NoValueException("长或者宽的数值非法"); } this.length = length; this.width = width; } /** 定义面积函数。 */ public int getArea() { return length*width; } } class ExceptionTest { public static void main(String[] args) { Rec r = new Rec(-3,4); int area = r.getArea(); System.out.println("area="+area); } }
四 编译时异常的应用@
4.1 理想处理事情
案例二:毕老师用电脑讲课。 两个对象: 老师: 属性:姓名。 行为:讲课。 电脑: 行为:运行。 package test; public class Test { public static void main(String[] args) { Teacher t =new Teacher("liuwang"); t.prelect(); } } class Notebook { void run(){ System.out.println("电脑运行了"); } } class Teacher { private String name; private Notebook notebook; Teacher (String name){ this.name=name; notebook = new Notebook(); } // 讲课 public void prelect (){ notebook.run(); System.out.println("讲课了"+name); } }
4.2 考虑异常
考虑问题:
- 1,电脑蓝屏-->异常。
- 2,电脑冒烟-->异常。
注意:
- 调用到了声明异常的方法,在这里到底是捕获好呢?还是声明好呢?
有具体的捕获处理方式吗?有,那就捕获,没有,那么声明。
我可以处理,重启就可以了,重启是电脑的功能。
1,电脑蓝屏-->异常
下面红色的部分是变化的部分
package test; public class Test { public static void main(String[] args) { Teacher t =new Teacher("liuwang"); t.prelect(); System.out.println("hello world"); } } class LanPingException extends Exception{ LanPingException(){super();} LanPingException(String s){ super(s); } } class Notebook { int statu=1; void run() throws LanPingException{ if(statu==1) throw new LanPingException("蓝屏了"); System.out.println("电脑运行了"); } void reset(){ statu=0; System.out.println("重启了...."); } } class Teacher { private String name; private Notebook notebook; Teacher (String name){ this.name=name; notebook = new Notebook(); } // 讲课 public void prelect (){ try { notebook.run(); } catch (LanPingException e) { notebook.reset(); //e.printStackTrace(); } System.out.println("讲课了"+name); } }
2,电脑冒烟-->异常。
注意:
- 方法上可以声明多个异常,并且需要多个catch来处理
package test; public class Test { public static void main(String[] args) { Teacher t =new Teacher("liuwang"); t.prelect(); System.out.println("hello world"); } } class LanPingException extends Exception{ LanPingException(){super();} LanPingException(String s){ super(s); } } class Notebook { int statu=2; void run() throws LanPingException, MaoYanException{ if(statu==1) throw new LanPingException("蓝屏了"); if(statu==2) throw new MaoYanException("冒烟了"); System.out.println("电脑运行了"); } void reset(){ statu=0; System.out.println("重启了...."); } } class Teacher { private String name; private Notebook notebook; Teacher (String name){ this.name=name; notebook = new Notebook(); } // 练习 void lianxi(){ System.out.println("做练习"); } // 讲课 public void prelect (){ try { notebook.run(); } catch (LanPingException e) { notebook.reset(); } catch (MaoYanException e) { e.printStackTrace(); } System.out.println("讲课了"+name); } }
结果
结果分析:这个结果是不正确的,明明电脑已经冒烟了但是,还在讲课
电脑冒烟了我直接处理不了,我处理的是让学生们去做练习。然后又声明出去(电脑冒烟处理不了,去找个师傅来修)
声明出去后,让调用讲课的知道。进行处理
package test; public class Test { public static void main(String[] args) { Teacher t =new Teacher("liuwang"); try { t.prelect(); } catch (MaoYanException e) { System.out.println("huanlaoshi"); //e.printStackTrace(); } System.out.println("hello world"); } } class LanPingException extends Exception{ LanPingException(){super();} LanPingException(String s){ super(s); } } class Notebook { int statu=2; void run() throws LanPingException, MaoYanException{ if(statu==1) throw new LanPingException("蓝屏了"); if(statu==2) throw new MaoYanException("冒烟了"); System.out.println("电脑运行了"); } void reset(){ statu=0; System.out.println("重启了...."); } } class Teacher { private String name; private Notebook notebook; Teacher (String name){ this.name=name; notebook = new Notebook(); } // 练习 void lianxi(){ System.out.println("做练习"); } // 讲课 public void prelect () throws MaoYanException{ try { notebook.run(); } catch (LanPingException e) { notebook.reset(); } catch (MaoYanException e) { lianxi(); //e.printStackTrace(); throw e; } System.out.println("讲课了"+name); } }
异常的转换@@
讲课中冒烟,问题可以临时解决,是冒烟问题没有直接处理,所以就使用throws声明。
但是发现,这个问题不应该属于讲课的问题。调用讲课方法的调用者是处理不了这个冒烟问题的。
该调用者能处理的应该是冒烟导致的课程进行不下去的问题。
应该在列出一个异常。课时停止异常。
例如:储户去存钱,你是银行,你把钱存到金库里面,可是呢金库出现问题了,你的做法应该是catch (处理)金库的问题
接下来,throw(抛出)异常说今天不能存了,不是说金库出现了什么具体的问题,直接告诉不能存了,至于金库的问题应该是你要解决的问题
package test; public class Test { public static void main(String[] args) { Teacher t =new Teacher("liuwang"); try { t.prelect(); } catch (NoPlanException e) { System.out.println("huanlaoshi"); } System.out.println("hello world"); } } class LanPingException extends Exception{ LanPingException(){super();} LanPingException(String s){ super(s); } } class Notebook { int statu=2; void run() throws LanPingException, MaoYanException{ if(statu==1) throw new LanPingException("蓝屏了"); if(statu==2) throw new MaoYanException("冒烟了"); System.out.println("电脑运行了"); } void reset(){ statu=0; System.out.println("重启了...."); } } class Teacher { private String name; private Notebook notebook; Teacher (String name){ this.name=name; notebook = new Notebook(); } // 练习 void lianxi(){ System.out.println("做练习"); } // 讲课 public void prelect () throws NoPlanException { try { notebook.run(); } catch (LanPingException e) { notebook.reset(); } catch (MaoYanException e) { lianxi(); //e.printStackTrace(); throw new NoPlanException("没有"); } System.out.println("讲课了"+name); } }
作者:8亩田
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.
本文如对您有帮助,还请多帮 【推荐】 下此文。
如果喜欢我的文章,请关注我的公众号
如果有疑问,请下面留言