zoukankan      html  css  js  c++  java
  • Java异常相关知识总结

    异常:

    概述:java程序运行过程中出现的错误

    常见的异常:
    StackOverflowError
    ArrayIndexOutOfBoundsException
    NullPointerException
    ClassCastException
    ParseException

    异常的分类:
    Trowable:
      1.--Error: a.相当于天灾人祸,虚拟机出现了问题
      2.--Exception:
        1).RuntimeException:运行过程中出现的异常 可以处理可以不处理,一般出现这种问题都是代码逻辑有问题,推荐修改代码
        2).编译期异常:出发之前因该检查的异常,必须处理,负责编译不通过

    1,编译时异常: 除了RuntimeException及其子类,Exception中所有的子类都是,这种异常必须要处理,要不编译通不过。

    2,运行时异常 :RuntimeException及其子类都是,这种异常不用处理,编译会通过,不过这样的程序会有安全隐患,遇到这种异常是需要改代码的。

    3,严重错误问题 :用Error进行描述,这个问题发生后,一般不编写针对代码进行处理,而是要对程序进行修正.通常都是由虚拟机抛出的问题。

    举例说明:

    异常分三类: 骑车去旅行:
      Error:走到半路上,发生山路塌陷,或者出现了泥石流,这个问题很严重,不是班长能够立马解决的。
      Exception:出门前,班长要看看车轮子以及车链子等是否还在
      RuntimeException:在骑车的过程中,有好路不走,偏偏要走石子路

    异常举例:

     1 //异常测试:
     2 //  a.除数为0
     3 //  b.数组越界
     4 public class HomeWork_02 {
     5     public static void main(String[] args) {
     6         System.out.println("start");
     7         f1();
     8         //f2();
     9         System.out.println("end");
    10     }
    11     //数组越界异常
    12     public static void f2(){
    13         int[]arr={1,2,3};
    14         System.out.println(arr[0]);
    15         System.out.println(arr[1]);
    16         System.out.println(arr[2]);
    17         //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
    18     }
    19     //除数为0异常
    20     public static void f1(){
    21         int a=23;
    22         int b=0;
    23         System.out.println(a/b);//ArithmeticException: / by zero
    24     }
    25 }

    jvm对异常的默认处理:
    a. 哪个线程出现的问题
    b. 异常的类型以及详细信息
    c. 调用栈信息
    d. 终止程序

    如下图为异常举例代码中数组溢出是jvm所报的错误:



     因为jvm处理异常的时候直接停止了程序,所以我们要学会自己处理异常:

    如何自己处理异常:
      a. try...catch...finally  
      b. throws



    1. try...catch...finally语句
      try {
      要检查的代码
        } catch (异常类型 对象名) {
          对异常的处理
       } finally {
        释放资源
      }
    a. 一种异常的情况

     1 public class ExceptionDemo_03 {
     2     public static void main(String[] args) {
     3         System.out.println("Start");
     4         int a =10;
     5         int b=0;
     6         try{
     7             System.out.println(a/b);
     8             System.out.println("one");
     9             System.out.println("two");
    10             System.out.println("three");
    11         }catch(ArithmeticException e){
    12             System.out.println("除数为0");
    13             System.out.println(e);
    14         }
    15         System.out.println("end");
    16     }
    17 }
    //问题:为什么e局部变量会有值?

    //如果try里面出现了异常, JVM会把异常信息封装成对应类型的异常对象。

     //然后和catch语句依次匹配,找到对应的异常类型,然后把它赋值给引用变量e

    输出结果:

    注意事项:
    a. try里面的代码越少越好,最好只放可能出现异常的代码
    b. try里面出现了异常,就不会执行try里面里面后序的代码
    c. ArithmeticException e 是局部变量, 作用范围是对应的catch语句。
    d. catch 捕获了异常,执行对应的处理,异常就不再存在了。

    b.多种异常的情况:
        a. 一个一个处理
        b. 一次性处理
        c. JDK7 新特性
          把多个处理方式相同的catch语句,合成一个catch语句。
            catch(类型1 | 类型2 | 类型3... e)
    注意事项:
    一个try语句中, 最多只会抛出一个异常,最多也只会执行一个catch语句
    如果异常没有兼容惯性,谁先谁后没关系,如果有兼容关系,那么父类应该方法在子类之后。
    JDK7新特性, 一个catch 语句不能出现子父类关系

    测试代码:

     1 /*多种异常的情况:
     2         a. 一个一个处理
     3         b. 一次性处理
     4        处理方式相同的catch语句,合成一个catch语句。
     5         catch(类型1 | 类型2 | 类型3... e)*/
     6 public class ExceptiomDemo_04 {
     7     public static void main(String[] args) {
     8         System.out.println("start");
     9         /*try {
    10             f1();
    11             f2();
    12             // f2()在后面的时候,执行到f1()的时候就不再往下执行了,没有输出arr[0],arr[1],arr[2]
    13         } catch (ArithmeticException e) {
    14             // System.out.println("除数为0");
    15             System.out.println("发生了异常");
    16         } catch (ArrayIndexOutOfBoundsException e) {
    17             // System.out.println("数组索引越界");
    18             System.out.println("发生了异常");
    19         } catch (Exception e) {
    20             System.out.println("其他异常");
    21         }*/
    22         try {
    23             f2();
    24             f1();
    25         } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
    26             System.out.println("除数为0或者数组索引越界");
    27         }
    28 
    29 
    30     }
    31     public static void f2(){
    32         int []arr={1,2,3};
    33         System.out.println(arr[0]);
    34         System.out.println(arr[1]);
    35         System.out.println(arr[2]);
    36         System.out.println(arr[3]); // ArrayIndexOutOfBoundsException: 3
    37     }
    38     public static void f1(){
    39         int a =10;
    40         int  b=0;
    41         System.out.println(a/b);// ArithmeticException: / by zero
    42 
    43     }
    44 }
    45   



    编译期异常和运行时异常:
    Exception:
      |-- 运行时异常: RuntimeException和其子类。
    可以显示处理,也可以不处理,一般出现运行时异常,都是代码逻辑有问题,推荐修改代码逻辑。
      |-- 编译期异常:其他类。无论运行时是否发生异常,都必须显示处理,否则无法通过编译。
    测试代码:

     1 import java.text.ParseException;
     2 import java.text.SimpleDateFormat;
     3 import java.util.Date;
     4 import java.util.SimpleTimeZone;
     5 
     6 //编译期异常和运行时异常:
     7 public class ExecptionDemo_05 {
     8     //一般不要在主方法中抛出异常,这里为方便在主方法中抛出异常
     9     public static void main(String[] args) throws ParseException {
    10         //运行时异常:
    11         int a=10;
    12         int b=0;
    13         try{
    14             System.out.println(a/b);
    15         }catch(ArithmeticException e){
    16             System.out.println("除0异常");
    17         }
    18         //编译期异常,不解决不能通过编译
    19         Date time=new Date();
    20         SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    21         String date=sf.format(time);
    22         System.out.println(date);
    23         Date date1=sf.parse(date);//ParseException 
    24     }
    25 }



    Throwable

    Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。

    类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。

      构造方法摘要: 
        Throwable()
          构造一个将 null 作为其详细消息的新 throwable。
        
    Throwable(String message)
          构造带指定详细消息的新 throwable。
      成员方法:
       

          返回此 throwable 的详细消息字符串。

          默认实现:getClass().getName()+“:”+getMessage();
          返回此 throwable 的简短描述。
        void printStackTrace() //推荐使用它,而且输出内容会用红色标识
            将此 throwable 及其追踪输出至标准错误流。

    注意:通常e.getMessage()并不能获取全部的错误信息,需要用到e.printStackTrace()查看完整错误信息,但是这个方法是void 只能在控制台输出

    测试代码:

     1 import java.text.ParseException;
     2 import java.text.SimpleDateFormat;
     3 import java.util.Date;
     4 
     5 //Throwable():、
     6 public class ExceptionDemo_06 {
     7     public static void main(String[] args) {
     8         String s = "2001/01/01 00:00:00";
     9         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    10         Date date = null;
    11         try{
    12             date=sdf.parse(s);
    13         }catch(ParseException e){
    14             System.out.println("解析异常");
    15             System.out.println(e.getMessage());
    16             System.out.println(e.toString());
    17             e.printStackTrace();
    18         }
    19     }
    20 }



    thorws

    定义功能方法时,需要把出现的问题暴露出来让调用者去处理。那么就通过throws在方法上标识。
    举例:
    村里出现了问题,如果能自己解决就自己解决,解决不掉就交给乡里,乡里解决不掉就抛给县里解决, 县里解决不掉,抛给市里,如果市里解决不掉,抛给省里,如果省里解决不掉,抛给中央。中央就直接干掉。

    throws: 把问题抛给调用者
    a.编译期异常
    b.运行期异常

    注意事项:
    不要在main()方法抛出异常,如果抛出异常就会执行JVM的默认处理。

    测试代码:

     1 import java.text.ParseException;
     2 import java.text.SimpleDateFormat;
     3 import java.util.Date;
     4 
     5 public class ExceptionDemo_07 {
     6     public static void main(String[] args) {
     7         String s = "2019/7-9 11:31:00";
     8         String pattern = "yyyy-MM-dd HH:mm:ss";
     9         Date date = null;
    10         try {
    11             date = string2Date(s, pattern);
    12         } catch (ParseException e) {
    13             e.printStackTrace();
    14         }
    15         System.out.println(date);
    16         int a = 10;
    17         int b = 0;
    18         int c = 0;
    19         try {
    20             c = f1(a, b);
    21         } catch (Exception e) {
    22             e.printStackTrace();
    23         }
    24         System.out.println("c = " + c);
    25         System.out.println("end");
    26     }
    27     //throw:告诉调用者,注意:调用这个方法可能会有某某异常
    28     public static Date string2Date(String s, String pattern) throws ParseException {
    29         SimpleDateFormat sdf = new SimpleDateFormat(pattern);
    30         return sdf.parse(s);
    31     }
    32     public static int f1(int a, int b) throws Exception{
    33         // return a / b;
    34         if (b != 0) {
    35             return a / b;
    36         }
    37         throw new Exception("除0异常");
    38     }
    39 }

    throw

    在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。

    测试代码:

    throws和throw的区别
    throws
    用在方法声明后面,跟的是异常类名
    可以跟多个异常类名,用逗号隔开 表示抛出异常,由该方法的调用者来处理
    throws表示出现异常的一种可能性,并不一定会发生这些异常

    throw
    用在方法体内,跟的是异常对象名
    只能抛出一个异常对象名
    表示抛出异常,由方法体内的语句处理
    throw则是抛出了异常,执行throw则一定会出现异常, throw抛出了一个实实在在的异常

     1 import java.util.Scanner;
     2 
     3 //举例:
     4        // 录入学生成绩 [0~100]
     5 public class ExecptionDemo_08 {
     6     public static void main(String[] args) {
     7         System.out.println("请输入学生成绩");
     8         Scanner sr =new Scanner(System.in);
     9         int score=sr.nextInt();
    10         //数据验证
    11         try{
    12             checkScore(score);
    13         }catch(Exception e){
    14             e.printStackTrace();
    15             
    16         }
    17     }
    18     public static void checkScore(int score) throws Exception {
    19         if(score<0||score>100){
    20             throw new Exception("score="+score);
    21         }
    22         //throw抛出了异常后,后面的语句就不再执行
    23         System.out.println("one");
    24         System.out.println("two");
    25         System.out.println("three");
    26     }
    27 }



    我们到底该怎么处理异常:
    原则:如果该方法知道如何处理,那用try...catch, 如果不知道怎么处理,就抛给它的调用者去处理。
    区别:
      如果try...catch,后续代码会执行。
      如果throws,后续代码不会被执行。


    try语句的变形
    try...catch
    try...finally
    try...catch...finally
    try...catch...catch...
    try...catch...catch...finally




    finally语句:
    特点:
      被finally控制的语句体无论出现异常还是没有出现异常,都会执行。
      特殊情况:在执行到finally之前jvm退出了. System.exit();
    作用:
      释放系统资源

    final和finally和finalize区别:

    final: 最终的
      类:不能被继承
      方法:不能被重写
      变量:常量
    finally:
      try语句的子句。
      finally里面的语句, 无论出现异常还是不出现异常,都会被执行。  
      用来释放资源。
    finalize:
      Object中的方法。
      对象被回收前,该方法会被自动执行。用来释放资源。
      手动调用该方法,对象不会被回收。

     1 import java.text.ParseException;
     2 import java.text.SimpleDateFormat;
     3 import java.util.Date;
     4 
     5 public class ExceptionDemo_09 {
     6     public static void main(String[] args) {
     7         String s = "2019/7/9 14:40:00";
     8         String pattern = "yyyy-MM-dd HH:mm:ss";
     9         SimpleDateFormat sdf = new SimpleDateFormat(pattern);
    10         try {
    11             Date date = sdf.parse(s);
    12         } catch (ParseException e) {
    13             e.printStackTrace();
    14         //finally只有在执行到finally之前虚拟机就退出的时候才会不执行
    15             //System.exit(0);
    16         } finally {
    17             System.out.println("finally子句");
    18         }
    19         System.out.println("end");
    20     }
    21 }            



    如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问结果是怎样的?
    finally语句会被执行
    第一次执行return语句,就已经生成了返回路径, 并把返回值保存起来了。
    后面在finally语句中修改变量,不会影响返回值。

    如果finally中也有return语句。
    最终执行的是finally中语句。

     1 public class ExceptionDemo10 {
     2     public static void main(String[] args) {
     3         System.out.println(method()); //40
     4     }
     5 
     6     public static int method() {
     7         String s = "2019/7/9 14:40:00";
     8         String pattern = "yyyy-MM-dd HH:mm:ss";
     9         SimpleDateFormat sdf = new SimpleDateFormat(pattern);
    10         int a = 10;
    11         try {
    12             a = 20;
    13             Date date = sdf.parse(s);
    14         } catch (ParseException e) {
    15             a = 30;
    16             return a;
    17         } finally {
    18             System.out.println("finally");
    19             a = 40;
    20             return a; //生成了另外一条返回路径
    21         }
    22     
    23     }
    24 }    


    自定义异常:
    类名就代表异常的种类(信息)
    编译期异常:继承Exception
    运行时异常:继承RuntimeException

    异常类:

    1 public class ScoreException extends RuntimeException {
    2     public ScoreException(){
    3         super();
    4     }
    5     public ScoreException(String message){
    6         super(message);
    7     }
    8 }

    测试类:

     1 public class EceptionDemo_11 {
     2     public static void main(String[] args) {
     3         System.out.println("请录入学生成绩;");
     4         Scanner scanner = new Scanner(System.in);
     5         int score = scanner.nextInt();
     6         // 数据验证
     7         /*try {
     8             checkScore(score);
     9             // 存入数据库
    10         } catch (ScoreException e) {
    11             e.printStackTrace();
    12         }*/
    13         checkScore(score);
    14     }
    15     private static void checkScore(int score) throws ScoreException{
    16         if (score < 0 || score > 100) {
    17             // throw new RuntimeException("score=" + score);
    18             throw new ScoreException("score=" + score);
    19         }
    20     }
    21 }

    异常注意的事项:(编译期异常)
    子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。
    如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
    如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws

    儿子不能比父亲更坏。一代只能比一代强。
    编译的时候,不检查运行时异常

  • 相关阅读:
    《炒股的智慧》
    python函数初识
    python文件操作
    python 表 字典 数据补充
    python深浅copy,is,id
    python列表字典小练习
    python列表字典练习
    python for/range练习
    python列表练习
    python每日小练习
  • 原文地址:https://www.cnblogs.com/zhaoyuan72/p/11166176.html
Copyright © 2011-2022 走看看