Java异常总结

Throwable

Error:严重问题,通常出现重大问题如:运行的类不存在或者内存溢出,服务器宕机,数据库崩溃等等。出现了error,靠我们的异常处理方式 try{}catch(){}和throws是处理不了的,必须找出哪个地方犯了这么严重的错误,然后修改代码,改正确了之后,程序才能够运行起来,否则程序绝对运行不起来。

代码演示:

public class Test {
    public static void main(String[] args) {
        show();
    }

    private static void show() {            
        show();     //java.lang.StackOverflowError栈内存溢出,这种情况必须更改代码
    }
}   

Exception

Exception下面RuntimeException下面的儿子都是运行期异常。运行时期异常可以处理也可以不处理

1)不处理:如果不处理,也不会报错(eclipse报红线),java就会用jvm默认的的处理方式,它就把异常的类型、原因、位置直接显示在了控制台。并且退出当前线程(可以理解为退出虚拟机),同时后面的代码是不能执行的。

2)处理:为了让后面的代码继续执行,那么我们处理异常, 我们采用try{}catch(){}

try{    
    可能发生问题的代码。  
}catch(异常类名 变量名){
    变量名.printStackTrace();//异常处理代码。
}finally{
    释放资源代码。(数据库,IO)
}

代码演示:

public static void main(String[] args) {
    try{
        System.out.println(10/0);
    }catch(ArithmeticException a) { //ArithmeticException a = new ArithmeticException();
        System.out.println("出错了,除数为零了");    //打印出:出错了,除数为零了
    }

    System.out.println("1111111111111111"); //打印出:1111111111111111,不会影响后面代码的运行
}

注意事项:

①一个try里面有多个异常怎么办?可以一个try后面跟多个catch,但是如果异常是平级关系,没有顺序问题。如果异常存在着子父关系,父一定要放在最后。

代码演示:

public static void demo1() {
    int a = 10;
    int b = 0;
    int[] arr = {11,22,33,44,55};
    try {
        System.out.println(a / b);  //运行时报错
        System.out.println(arr[10]);    //此代码不会执行
        arr = null;         //此代码不会执行
        System.out.println(arr[0]); //此代码不会执行
    } catch (ArithmeticException e) {
        System.out.println("除数不能为零");
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("索引越界了");
    } catch (Exception e) {         //Exception是父类  父类一定放在最后面 
        System.out.println("出错了");
    }
    System.out.println("over"); //不影响后面代码的运行
}

②:可以用一个catch, catch里面写一个Exception就可以了

代码演示:

public static void demo1() {
    int a = 10;
    int b = 0;
    int[] arr = {11,22,33,44,55};

    try {
        System.out.println(a / b);
        System.out.println(arr[10]);
        arr = null;
        System.out.println(arr[0]);
    } catch (Exception e) {         //多态
        System.out.println("出错了");
    }                           
    System.out.println("over");
}

③了解JDK7的新特性。格式:try{}catch(异常1 | 异常2 | 异常3 ... 变量名){}

代码演示:

public static void main(String[] args) {
    int a = 10;
    int b = 0;
    int[] arr = {11,22,33,44,55};

    //JDK7如何处理多个异常
    try {
        System.out.println(a / b);
        System.out.println(arr[10]);
    } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
        System.out.println("出错了");
    } 
}

④我们一直在处理异常的时候都是打印的一句话,虽然提示了我们有错误,但是没有告诉开发人员是哪一行代码出错,没有告诉开发人员是哪个异常! 那这样的话,不利于开发人员对代码进行维护,所以我们就有了标准的异常catch代码,既能打印出异常消息,显示出哪一行出的错,又能不影响后面的代码执行。首先介绍:Throwable中的方法:

public String getMessage():返回的是异常的消息字符串。

public String toString():返回异常的简单描述信息。全路径类名 : 消息字符串

public void printStackTrace():把错误信息显示在控制台。

代码演示:

public static void main(String[] args) {
    try {
        System.out.println(1/0);
    } catch (Exception e) {         //Exception e = new ArithmeticException("/ by zero");
        System.out.println(e.getMessage());//   / by zero
        System.out.println(e);      //java.lang.ArithmeticException: / by zero
        e.printStackTrace();        
        /*java.lang.ArithmeticException: / by zero at           com.heima.exception.Demo5_Throwable.main(Demo5_Throwable.java:18) 
                                                    */
    }
}

⑤finally的程序除了虚拟机挂掉,其他的时候都会执行的,所以把一些必须要执行的重要代码放在finally里面执行。比如释放资源代码。
⑥final,finally和finalize的区别:

  • final可以修饰类,不能被继承;修饰方法,不能被重写;修饰变量,只能赋值一次

  • finally是try语句中的一个语句体,不能单独使用,用来释放资源

  • finalize是一个方法,当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法

面试题

如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问是在return前还是return后。

public static void main(String[] args) {
    System.out.println(method());       //30
}
public static int method() {
    int x = 10;
    try {
        x = 20;
        System.out.println(1/0);
        return x;
    } catch (Exception e) {
        x = 30;
        return x;   //当程序执行到这儿,内存中已经生成了一条"return 30"的路径,
        //但是发现finally还没有执行呢,就又去执行了finally里面的内容让x变成了40,
        //但是"return 30"的路径已经生成了,即使x变成了40也是没用的!
        //接着还是会继续执行"return 30" 然后结束方法。
    } finally {
        x = 40;                         
    }
}

⑦如果处理运行期异常,我们还可以采用Throws 声明异常,但是我们一般不用(为什么?请看下面解释)。编译期异常:Exception下面非RuntimeException 的异常;运行期异常:RuntimeException下的异常。如果是运行期异常的话我们声明和不声明是一样的。而且只要运行时出现异常的话,声明和不声明异常,后面的代码都不会再继续执行了,那么我们为什么有个声明异常这种处理方式呢?这就引出了编译期异常,编译期异常就是在开发人员编写代码的时候,程序提示你这儿以后可能会出现一些常见的问题,让咱们在写代码的时候就要针对这常见的问题采取措施,不要等运行的时候出错了再去解决,因为这个问题很常见,可以预防,所以java呢为了这样提示开发人员就让开发人员在编写的时候都不让开发人员编译通过,必须要采取措施,而开发人员采取的措施一个就是用try{}catch(){} ,另一个就是不用管这个异常啦,直接抛给虚拟机(throws声明一下),这两种方式都证明开发人员知道这儿可能会出现异常,并采取措施了。 所以声明异常是给编译期异常准备的。 运行期异常虽然能用,但是没啥实际意义,所以运行期异常我们一般还是用try{}catch(){}。

自定义异常

有时候需要我们自己定义一些异常,很简单,只需要建一个类(类名见名知意) 继承这个异常体系(继承Exception或者其儿子),写一个有参构造方法用来传入异常信息,遇到特定业务的时候throw就可以了。

代码演示:

//建一个类(类名见名知意)继承这个异常体系(继承Exception或者其儿子)
class AgeOutOfBoundsException extends Exception {   
  
    public AgeOutOfBoundsException() {
        super();
    }
    public AgeOutOfBoundsException(String message) {//写一个有参构造方法,用来传入异常信息
        super(message);             
    }       
}

public class Demo_Exception {

    public static void main(String[] args) throws Exception {//p.setAge(-17);main方法中调用setAge方法的时候,因为setAge方法体上声明了一个编译期异常 所以main方法的方法体上也要声明该编译期异常
        Person p = new Person();
        p.setAge(-17);
        System.out.println(p.getAge());
    }

}

class Person {
    private String name;
    private int age;
    public Person() {
        super();
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) throws Exception{   
        //方法体内如果有 "throw 编译期异常对象" ,则方法体上必须用throws声明该编译期异常
        if(age >0 && age <= 150) {
            this.age = age;
        }else {
            throw new AgeOutOfBoundsException("年龄非法");  //遇到特定业务的时候throw就可以了
        }
    }


}
throw和throws的区别:

throw 写在方法里面,后面跟对象,只能跟一个对象

throws 写在方法声明上,后面跟异常类型,可以跟多个异常类型并用逗号隔开

字符类关系中的异常

a:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)

class Fu{
    public void show() throws IOException{  //父类方法声明 IOException 

    }
}
class Son extends Fu{
  
    public void show() throws IOException{  //这样是可以的 声明和父类相同的IOException

    }
  
    public void show() throws FileNotFoundException{
        //这样是可以的,声明父类异常的儿子,也就是IOException的子类FileNotFoundException

    }

    public void show() throws Exception{
        //这样是不行的 声明父类异常的父类,也就是IOException的父类Exception
    }
            
} 

b:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常。

class Fu{
    public void show() throws IOException,NoSuchMethodException{

    }
}
class Son extends Fu{
    public void show() throws IOException{//这样写可以 子类只能抛出相同的异常或者是他的子集

    }
   
    public void show() throws ParseException{//这样做是不行的 子类不能抛出父类没有的异常

    }

}

c:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常;如果子类方法内有异常发生,那么子类只能try,不能throws

class Fu{
    public void show(){

    }
}
class Son extends Fu{
    public void show(){//这样做可以 如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常

    }

    public void show() throws Exception{//这样做 不可以

    }

    public void show() {
        //如果被重写的方法没有异常抛出,而且子类方法内有异常发生,那么子类只能try,不能throws    
        try {
            FileInputStream fis = new FileInputStream("xxx.txt");  
            //new FileInputStream("xxx.txt");这句话有个编译期异常
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

}

好了今天就先说到这了,明天继续。想了解更多学习知识,请关注微信公众号“阿Q说”,获取更多学习资料吧!你也可以后台留言说出你的疑惑,阿Q将会在后期的文章中为你解答。每天学习一点点,每天进步一点点。

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

推荐阅读更多精彩内容

  • 八、深入理解java异常处理机制 引子try…catch…finally恐怕是大家再熟悉不过的语句了, 你的答案是...
    壹点零阅读 1,526评论 0 0
  • 提示: 几种常见异常ArithmeticException数学算数错误异常ArrayIndexOutOfBound...
    孙睿888阅读 409评论 0 0
  • 如图可以看出所有的异常跟错误都继承与Throwable类,也就是说所有的异常都是一个对象。 从大体来分异常为两块:...
    john_leventon阅读 153评论 0 0
  • 异常 概念 异常是程序运行过程中可能发生的一类事件。 当方法中发生错误时,该方法会创建一个对象——异常对象——并将...
    FoxLayla阅读 377评论 0 0
  • 一、服务器相关 1、服务器的分类: 2、服务器的搭建: 二、样式表 1、内部样式表(嵌套到页面中) 注意:每个CS...
    王梓懿_1fbc阅读 246评论 0 0