异常

一、异常的产生

先看下面的这个demo:

/*
 * 异常的产生
 */

public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println(0/0);
        System.out.println("hello world");
    }
}

此时程序就产生 的异常如下:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at exceptions.ExceptionDemo.main(ExceptionDemo.java:11)

分析:

  • JVM检测到了问题(0是除数的问题),于是程序发生了异常
  • JVM就把这个异常进行了对象的封装new ArithmeticException()
  • 异常对象被抛给调用者main中,main方法接收到这个异常后,由于程序中没有对异常进行处理的方法,因此mian方法也不能处理此异常,于是异常又被抛出到JVM中
  • JVM接受到异常后,采取了默认的处理措施,停止运行程序,于是后面的这个syso语句没有执行。

异常也是对象,上述例子中异常对象的描述类是ArithmeticException,它是用来描述数学中算数问题的 异常类。比如还有常见的空指针异常描述类NullPointerException。

二、异常的继承体系

Throwable类是所有异常和错误的父类

  • Error 错误

  • Exception 异常

    错误:程序出现了严重的问题,不修改代码,根本不能运行,人得了非典,艾滋,癌

    异常:程序出现了比较轻的问题,处理掉之后,继续运行,人得了阑尾炎,感冒

Exception类是所有异常的父类

  • 非RuntimeException
  • RuntimeException

Throwable中的方法:

  • String toString()重写Object类的方法,异常信息的详细描述?
  • String getMessage() 返回异常信息的简短描述
  • void printStackTrace() 异常信息输出到控制台

三、异常的两种处理方式

  1. 直接处理掉异常

    demo:

    try{
      尝试捕获异常的代码
    }catch(异常类 异常变量){
      异常处理代码
    }
    
  2. 第二种处理方式就是抛出异常

    • throw 手动抛出异常,后面写的是new异常的对象,写在方法中
    • throws 方法声明抛出异常,后面写的是异常类,写在方法的声明上

    demo:

    /*
      异常第二种处理方式,抛出异常
      throw throws的用法
    
      ExceptionDemo2.java:21: 错误: 未报告的异常错误Exception; 必须对其进行捕获或声明
      以便抛出
          throw new Exception();
      方法中,有异常抛出,但是没有处理过,因此编译失败
      异常的编译提示,是Java编译时的最后提示
    */
    
    class ExceptionDemo2 
    {
     public static void main(String[] args) throws Exception
     {
         //System.out.println("Hello World!");
         //main中调用了method方法,方法抛出了异常
         //main有2个选择方法,一个是try...catch
         //另外一个是,异常我也不处理,交给我的调用者处理
         method(-5);
     }
     /*
        如果方法的参数小于0
        程序出现异常,如果参数大于0 ,程序是正常的
        方法自己,不想处理这个异常,把异常交给调用者处理
        在方法声明上,抛出异常,声明出来有异常,交给调用者
        throws 异常类
     */
     public static void method(int x)throws Exception{
        if(x < 0)
            //程序出现了问题
            //手动抛出异常
            throw new Exception("程序出现了异常了");
         
         else
             System.out.println("程序正常");
     }
    }
    

四、多层异常的处理

demo

/*
  多层的异常处理方法调用
*/

class ExceptionDemo3 
{
    public static void main(String[] args) 
    {
        //System.out.println("Hello World!");
        try{
        methodA();
        }catch(Exception e){
        
        }
    }

    public static void methodA()throws Exception{
       methodB();
    }

    public static void methodB()throws Exception{
        methodC();
    }

    public static void methodC()throws Exception{
       throw new Exception();
    }
}

五、finally代码块

  • finally可以跟随try出现,也可以跟随try...catch出现
  • finally代码块中的程序,必须要运行
  • finally实际的开发意义,释放资源

demo

/*
   finally代码块
   一定要执行
*/

class ExceptionDemo4 
{
    public static void main(String[] args) 
    {
        try{
        method(1);
        }catch(Exception e){
           e.printStackTrace();
        }finally{
            System.out.println("这里的程序必须执行");
        }
    }

    public static void method(int x)throws Exception{
       if(x == 1)
           throw new Exception("异常了!!");
       else
           System.out.println("程序正常了");
    }
}

一个finally的特例:

/*
demo:true or false
*/
class ExceptionDemo5{
  public static void main(String[] args){
    System.out.println(method());
  }
  public static boolean method(){
    
    try{
      return false;
    }catch(Exception e){
      
    }finally{
      return true;
    }
  }
}
//结果:true


/*
demo2:2 or 10
开发中,不要再try catch中写return
*/
class ExceptionDemo6{
  public static void main(String[] args){
    System.out.println(method());
  }
  public static int method(){
    int i = 1;
    try{
      return ++i;
    }catch(Exception e){
      return 100;
    }finally{
       i=10;
    }
  }
}
//结果:2

六、编译时期的异常

调用一个方法,这个方法抛出一个异常,此时调用者必须处理异常,否则编译失败。

Demo

/*
   编译时期的异常 
*/
class ExceptionDemo2{
    public static void main(String[] args){
        System.out.printf("hello wordl");
        method();
    }

    public static void method() throws Exception{}
}

结果如下:

ExceptionDemo2.java:10: 错误: 未报告的异常错误Exception; 必须对其进行捕获或声明
以便抛出
        method();
              ^
1 个错误

改进,加上try catch对异常进行处理,错误提示消失。

/*
   编译时期的异常 
*/

class ExceptionDemo2{
    public static void main(String[] args){
        System.out.printf("hello wordl");
        try{
        method();
        }catch(Exception e){}
    }

    public static void method() throws Exception{}
}

七、运行时期的异常

运行时期的异常一旦发生了,后面的所有程序都不会接着往下执行,所以设计运行时期的异常的初衷就很明显了,这个异常就是让开发人员看的,发生运行异常,就必须去修改原代码,而不是去处理异常。

Demo

/*
  运行时期的异常的特点
*/
class ExceptionDemo3{
    public static void main(String[] args){
        //调用者不知道方法会出现异常,所以就不用处理
        //这种时候,需要修改代码,而不需要处理
        method();
    }

    public static  void method(){
        //手动抛出一个异常

        throw new RuntimeException();
    }
}

Demo2

/*
  要求:计算正方形面积,边长的平方
  定义方法:求面积,返回结果
*/
class ExceptionDemo4{
    public static void main(String[] args){
        
        System.out.println(method(-8));
    }

    public static  int method(int num){
        if(num <= 0){
            //边长不合法,没有必要计算
            throw new RuntimeException("<= 0");
        }
        return num * num;
    }
}

常见的运行时期的异常:

异常对象 实际含义
IndexOutOfBoundsException 越界(字符串,和数组)
NullPointerException 空指针
ClassCastException 类型转换异常
NoSuchElementException 没有元素被取出
IllegalArgumentException 无效参数异常

八、自定义异常

Java中异常体系,将很多的情况都做了异常封装,但是实际的开发中,不可能把所有的异常都描述完毕,需要自定义的异常,用来描述自己程序中可能发生的异常。

自定义异常步骤:

  1. 定义类,后缀名Exception继承Exception类,或者继承RuntimeException
  2. 异常信息,自定义的异常类的构造方法,把异常信息使用super传递到父类

注意:只有异常类,才具备可抛性 throw new 异常体系的类

通过刚才案例:

  1. 如果一个方法中,抛出多个异常,必须要throws声明多个异常(运行时起除外)
  2. 调用者,使用多个catch进行异常的捕获
  3. 多个catch中,最大(继承关系)的父类,写在最后面,否则编译失败

Demo

package exceptions;

/*
 * 自定义异常
 */

//负数异常
class FuShuException extends Exception{
     FuShuException(){}

     FuShuException(String info){
        super(info);
    }
}

//0异常
class ZeroException extends Exception{
    ZeroException(){}

    ZeroException(String message){
        super(message);
    }
}


public class ExceptionDemo5 {
    public static void main(String[] args) {
        try{
        getArea(0);
        }catch(FuShuException e){ //多异常,就多catch,范围越大的往后写
            e.printStackTrace();
        }catch(ZeroException e){
             e.printStackTrace();
        }
    }
    public static int getArea(int num) throws FuShuException,ZeroException{
        if(num < 0){
            throw new FuShuException("边长是负数");
        }
        else if(num == 0){
             throw new ZeroException("边长为0");
        }

        return (int)Math.pow(num,2);
    }
}

九、继承异常

前提:子类重写父类的方法

  • 父类的方法抛出了异常,子类重写后,异常:父类抛异常,子类可抛可不抛,但是,如果子类抛,不能抛出比父类还大的异常
  • 父类的方法不抛异常,子类重写后,子类不能抛出异常。如果子类重写的方法中,调用了一个抛异常的方法,子类别无选择,只能try...catch处理异常

demo

package exceptions;

/*
 * 自定义异常
 * 1.父类方法抛异常,子类重写后可抛可不抛,若是抛,则要小于父类(前提是子类重写了父类方法)
 * 2.父类方法不抛异常,子类也不能抛,若是子类调用的方法抛了异常,子类只能try catch
 */

//A是父类异常类
class AException extends Exception{

}
//B继承A
class BException extends AException{
    
}
//C和A是兄弟类
class CException extends Exception{
    
}

class Zi extends Fu{
    public void show() throws BException{}
}

class Fu{
    public void show() throws AException{}  
}

public class ExceptionDemo6 {
    public static void main(String[] args) throws AException{
        Fu f = new Zi();
       
          f.show();
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容

  • 通俗编程——白话JAVA异常机制 - 代码之道,编程之法 - 博客频道 - CSDN.NEThttp://blog...
    葡萄喃喃呓语阅读 3,176评论 0 25
  • Java异常类型 所有异常类型都是Throwable的子类,Throwable把异常分成两个不同分支的子类Erro...
    予别她阅读 924评论 0 2
  • 一、多态 1. 概述 理解:多态可以理解为事物存在的多种体(表)现形态。例如:动物中的猫和狗。猫这个对象对应的是猫...
    陈凯冰阅读 337评论 0 1
  • 今天下午饭都没有吃饱就把饭给倒了,因为下午吃饭时间只有半小时,而我们在四楼上班,食堂离我们又远,走到食堂都5:10...
    掌心日记阅读 393评论 0 0
  • 大伟满足了若希对男人所有的幻想。知情识趣,浪漫体贴。明知他永远不缺女人,还是愿意默默守候,奢望有天能感动他。 这天...
    烟行阅读 271评论 0 4