java-异常处理2

一 编译时异常和运行时异常的区别

java认为如果你的程序有问题,你应该让调用者知道.

例如:面包,长毛了.用户去买了,用户可能会挂 .应该在面包上贴上标签(异常).

java

如果在函数内抛出Exception//编译失败,因为编译器在检查语法时发生了错误。

该程序已经出现问题,Java认为这个程序本身存在隐患,
需要捕获或者声明出来(你要么把问题处理,要么把问题标识出来让调用知道)

 

1.1 抛RuntimeException不要捕获,不声明?

不是功能本身发生的异常,而是因为比如调用者传递参数错误而导致功能运行失败。(如数组下标越界)
这时也是问题,需要通过异常来体现,但是这个异常不要声明出来的。
声明的目的是为了让调用者进行处理
不声明的目的是不让调用者进行处理,就是为了让程序停止,让调用者看到现象,并进行代码的修正。★★★★★

1.2异常分两种

1,编译时异常:编译器会检测的异常。
2,运行时异常:编译器不会检测的异常。不需要声明。声明也可以,如果声明了,无外乎就是让调用者给出处理方式。常见的异常

  1. ArrayIndexOutOfBoundsException
  2. IllegalArgumentException
  3. NullPointerException
  4. 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,电脑冒烟-->异常
注意:

  1. 方法上可以声明多个异常,并且需要多个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);
    }
    
}

 

posted @ 2018-01-09 18:44  8亩田  阅读(232)  评论(0编辑  收藏  举报