[18]异常

版权声明:嘤嘤嘤,小白的东西,大牛们应该看不上吧。 https://blog.csdn.net/qq_37384180/article/details/83116120

异常:英文单词就是Exception,字面意思,可以理解为意外。

对于初学者我来说,现在的代码都是理想状态下,所以为了考虑一个代码的安全性以及健壮性,一个程序是离不开异常的。

【异常类继承关系】

Java中,所有异常的父类为Throwable

Throwable类有两个子类,Exception类和Error

Error类:为无法处理的异常。字面意思,错误。一般出现这种情况,都是系统级错误,会反馈给JVM,来停下程序。

Exception类:为可处理异常。比如RuntimeException或是ArrayIndexOutOfBoundsException

Exception类中分两种:运行时异常或是非运行时异常(编译时异常)

运行时异常:RuntimeException。例如:NullPointException,ArrayIndexOutOfBoundsException等。

非运行时异常:除了RuntimeExpcetion之外的异常都是非运行时异常,异常类比较多。所以初学者的我,暂时只用Exception类

运行时异常,Java编译器不要求必须进行声明和捕获。

非运行时异常,Java编译器强制必须进行声明和捕获,不然编译不给通过

那么看看异常在平常程序中起到的作用。

举个例子,我写了一个方法,计算长方形面积,形参为长和宽。理想状态下,输入3和4,得出12

但如果是-3呢?0呢?那么面积为-12?0?岂不是很恐怖

class Rectangle{
    private double length;
    private double width;
    public void setLength(double length){
        this.length=length;
    }

    public double getLength(){
        return this.length;
    }

    public void setWidth(double width){
        this.width=width;
    }

    public doube getWidth(){
        return this.width;
    }

    public Rectangle(double length,double width){
        this.length=length;
        this.width=width;
    }

    public double getArea(){
        return length*width;
    }
}

class Demo{
    public static void main(String[] args){
        Rectangle r=new Rectangle(3.0,4.0);
        System.out.println(r.getArea());
    }
}

打印结果: 

打印结果:12.0,那么如果将参数改成负数

代码修改: 

class Demo{
    public static void main(String[] args){
        Rectangle r=new Rectangle(-3.0,4.0);
        System.out.println(r.getArea());
    }
}

打印结果: 

打印结果:-12。居然有长方形的面积为0?

这时候如果调用者没看到,以为运行正常,没出错,那么导致的后果就是可能没人发现。

所以这时候将异常加入进来前,要么直接用异常子类,或是自定义异常类。

很多时候可使用异常子类,但如果你感觉异常子类并不能完好的反馈出异常信息,可以自定义异常类。

如果自定义异常类,那么就要考虑要继承关系:

【继承RuntimeException还是Exception类】

Exception:

如果在函数中抛出Exception类,就已经不是正常运行的异常了。

所以编译器会认为有隐患。需要声明或是捕获出来。

声明的意义就是为了告诉调用者这里有异常,进行处理。

RuntimeException:

RuntimeException之所以是Runtime是因为代码本身语法编译没有问题

异常的原因可能是因为传参错误或是其他逻辑问题。

不声明的意义就是不让调用者知道这里有异常,调用者可能传参或是逻辑错误时,立刻让程序停止,让调用者看到现象

将原本错误的参数或逻辑修改。 

所以我们这里是为了让调用者知道自己传参的错误,那么我们应该继承于RuntimeException

【RuntimeException例子】

class Rectangle{
    //code .........

    public double getArea(){
        if(width<=0 || length<=0){
            throw new RuntimeException("你的长或宽有误,请及时修正");
        } 
        return length*width;
    }
}
//异常类继承与RuntimeException
class ValuesException extends RuntimeException{
    public ValuesException(){
        super();
    }

    public ValuesException(String message){
        super(message);
    }
}

class Demo{
    public static void main(String[] args){
        Rectangle r=new Rectangle(-3.0,4.0);
        System.out.println(r.getArea());
    }
}

【例子2】

class Person{
    private String name;
    private int age;

    //code.....
    
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }

    public String toString(){
        if(age>=200 || age<=0){
            throw new AgeException("你是神仙啊?");
        }
        return name+"'age is"+age;
    }
}

class AgeException extends RuntimeException{
    public AgeException(){
        super();
    }

    public AgeException(String message){
        super(message);
    }
}

class Demo{
    public static void main(String[] args){
        Perosn p=new Person("lgb",1500);
        System.out.println(p.toString());
    }
}

但如果此时我将姓名调至1500,那岂不是很恐怖?

此时也是一样需要RuntimeException来修正。

【知识点】

抛出异常:throw new 异常类

声明:可以理解为汇报调用者异常,用throws 异常类,抛出什么异常对象,异常类就是什么

捕获:处理问题 ,try/catch,try是可能会出现异常的代码,catch为解决异常的代码

【Exception例子】

教师上Java课用电脑,是不是有可能出现电脑蓝屏的情况?电脑蓝屏老师可以处理吗?当然有,重启呗。。。

所以这个是可以解决的问题。而电脑蓝屏是运行时会出现的问题,所以应该写在run方法中,这个异常抛出后,要声明。

而调用者看到后。捕获即可

接下来,还有可能教师将水打翻了,电脑凉了。这个也是可以处理的,只不过只能间接性处理,做练习。但是问题本质还未解决

因为培训机构里面电脑坏了,只能给出间接处理,比如换电脑,或是做练习。电脑坏了并不会直接处理,只能汇报给维修公司。

那么就需要另一个异常。称为异常转换

/*
    教师类
*/
class Teacher{
    private String name;
    public void setName(String name){
        this.name=name;
    }    
    public String getName(){
        return name;
    }
    //讲课方法
    public void teach(Computer c)throws RepairException{
        try{
            c.run();  
        }catch(BlueScreenException e){
            c.reset(); 
        }catch(InletWaterException e){
            c.test();
            throw new RepairCompany("汇报维修公司");
        }
            System.out.println("讲课"); 
    }
    //重启方法
    public void reset(){
        System.out.println("电脑重启了");
    }
    //做练习方法
    public void test(){
        System.out.println("做练习吧");
    }
}
/*
    电脑类
*/
class Computer{
    private int state;//如果state=1,电脑蓝屏,如果state=2,电脑进水
    public void setState(int state){
        this.state=state;
    }
    public int getState(){
        return state;    
    }
    public void run() throws BlueScreenException{
        System.out.println("电脑开机了");
        if(state==1){
            throw new BlueScreenException("电脑蓝屏");
        }
        if(state==2){
            throw new InletWaterException("电脑进水");
        }
    }
}
/*
    测试类
*/
class Demo{
    public static void main(String[] args){
        Teacher t=new Teacher("lgb");
        Computer c=new Computer();
      //c.setState(1);
        c.SetState(2);
        try{
            t.teach(c);
        }catch(RepairCompanyExpcetion e){
            e.printStackTrace();
        }
    }
}

/*
    蓝屏异常类
*/
class BlueScreenException extends Exception{
    public BlueScreenException(){
        super();
    }

    public BlueScreenException(String message){
        super(message);
    }
}

/*
    进水异常类
*/
class InletWaterException extends Exception {
    public InletWaterException(){
        super();
    }
    public InletWaterException(String message){
        super(message);
    }
}

/*
    汇报维修公司类
*/
class RepairCompanyException extends Exception {
    puhblic RepairCompanyException(){
        super();
    }
    puhblic RepairCompanyException(String message){
        super(message);
    }
}

异常在继承或实现中的细节:

1.在子类继承父类的情况下,若父类声明异常,那么子类只能声明异常或异常的子类,或是不声明

2.当父类声明多个异常的情况下,子类可以声明多个中的任意组合,包括不声明

3.当父类未被声明异常,那么子类也无法声明异常

继承与接口的问题:

接口和父类没有声明异常,但是因为子类遇到了异常,需要抛出并声明异常。

解决:

因为父类和接口不一定会有声明(throws)异常,那么只能捕获(try catch),如果发现这个事情解决不了。可以先尝试间接性处理,然后异常转换成RuntimeException或者其子类并抛出,让调用者解决。(因为父类没声明异常,子类也无法声明,但是RuntimeException是可以在省略声明或捕获的异常的类,所以可以这么进行异常转换)

猜你喜欢

转载自blog.csdn.net/qq_37384180/article/details/83116120
18