Java中的异常Throwable分为三种情况
- Error:严重的错误,是我们无法处理的问题,比如OOM,内存溢出问题
- 运行时异常RuntimeException:编译器不会检查的异常,可以处理也可以不处理。但这个异常我们通常不处理,因为运行时异常一般都是我们写的程序代码出了问题。与其抛出解决异常,不如直接把代码修改正确就行。比如数组下标越界,访问null指针,类型转换错误等。
- 编译时异常: 除了RuntimeException运行时异常以外的异常都是编译时异常。这种异常必须要处理,如果不处理程序就无法通过编译。比如File对象中有不存在的路径文件。
如果程序出现了问题,我们没有做任何处理,JVM会给出一个默认的处理结果。把异常的名称,相关的原因,以及出现问题的相关信息,包括位置输出在控制台
同时程序结束,后面的代码不会运行
- 那么为什么会有异常的抛出与处理机制呢?
- 异常举例
- 运行时异常举例
- 编译时异常举例
- 处理异常
- try-catch-finally
- catch语句块中的方法
- printStackTrace()
- throws
- throw
- throw举例
- throws举例
因为在程序运行的过程中,可能会出现意想不到的情况,比如读取文件时发现文件不存在,这个就是异常。异常不一定会发生,但是如果发生了,程序要能够抛出异常,避免因为一个异常,而导致整个程序的崩溃,这个后果可能会非常严重。
抛出和处理异常后,try-catch-finally语句块之后的程序代码依旧可以正常的运行,而如果不做异常处理,之后的程序代码就不会运行了。
异常举例 运行时异常举例package review.ExceptionDemo; public class demo4 { public static void main(String[] args) { //运行时异常举例 System.out.println("befor异常之前"); int r1 = div(2,0); System.out.println(r1); System.out.println("after异常之后"); } public static int div(int a,int b){ return a/b; } }
除数不能为0,发生异常,程序直接停止,不会继续向下运行
package review.ExceptionDemo; public class demo4 { public static void main(String[] args) { //运行时异常举例 int[] arr = {1,2,3,4,5}; int r2 = array(arr); System.out.println(r2); } public static int array(int[] arr){ return arr[arr.length]; } }
数组下标越界异常
在编译的时候就会出现错误信息提示,说明这里可能会出现异常,但是程序中又没有对这个异常进行处理,所以不能编译
package review.ExceptionDemo; import java.text.SimpleDateFormat; import java.util.Date; public class demo5 { public static void main(String[] args) { //编译时异常举例 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String s ="2021-10-18"; try { Date date = sdf.parse(s); System.out.println(date); }catch (Exception e){ e.printStackTrace(); } } }
修改后可以正常的编译程序,并且捕获异常
那么现在的问题是,我们知道这里可能会出现异常,为了避免程序的崩溃,所以我们需要对这个异常进行抛出并且处理
异常的处理格式:
1、try…catch…finally
2、throws
try...catch...finally的处理格式: try{ 可能会出现问题的代码; }catch(异常的类名 变量名){ 针对问题的一些处理; 没有发生此catch对应的异常,此catch中的语句不会执行 }finally{ 释放资源的代码 不管是否发生异常,都会执行finally中的语句 }
package review.ExceptionDemo; public class demo6 { public static void main(String[] args) { System.out.println("before"); int a = 5; int b = 0; //try...catch处理一些可能会出现问题的代码 try { System.out.println(a/b); }catch (ArithmeticException a1){ System.out.println("除数不能为0"); } System.out.println("after"); } }
当然,一段代码中也可能有多个异常,有几个异常就需要写几个catch语句
package review.ExceptionDemo; public class demo6 { public static void main(String[] args) { System.out.println("before"); int a = 5; int b = 0; try{ System.out.println(a / b); int[] arr = {1, 2, 3, 4, 5}; System.out.println(arr[5]); }catch (ArithmeticException a1){ System.out.println("除数不能为0 "); }catch (ArrayIndexOutOfBoundsException a2){ System.out.println("数组下标越界"); } } }
注意:
- 异常的类型尽可能的准确,如果能明确异常的种类时,就不要用该异常的父类
比如IOException可以处理的异常,不要用Exception来概括 - 当多个异常之间是平级的关系时,多个catch语句没有前后顺序关系,谁在前谁在后都行。但是一旦出现了父类继承的关系,父类异常必须在后。
- 一旦try里面的代码出现了问题,就会去匹配catch里面的异常,继续执行catch中的语句。try里面的代码就停在了出现问题的那一步。但是try-catch语句后面的代码可以正常执行。
package review.ExceptionDemo; public class demo6 { public static void main(String[] args) { try{ System.out.println("before"); int[] arr = {1, 2, 3, 4, 5}; System.out.println(arr[5]); System.out.println("after"); } catch (ArrayIndexOutOfBoundsException a2){ System.out.println("数组下标越界"); System.out.println("继续执行"); }finally{ System.out.println("不管是否发生异常,都会执行"); } System.out.println("之后的程序代码正常执行"); } }
package review.ExceptionDemo; public class demo6 { public static void main(String[] args) { try{ System.out.println("before"); int[] arr = {1, 2, 3, 4, 5}; System.out.println(arr[3]); System.out.println("after"); } catch (ArrayIndexOutOfBoundsException a2){ System.out.println("数组下标越界"); System.out.println("继续执行"); }finally{ System.out.println("不管是否发生异常,都会执行"); } } }
JDK7的新特性,可以一次性处理多个异常
try{ 可能会出现问题的代码 }catch(异常类名1|异常类名2|... 变量名){ 处理异常的语句 }
public class demo7 { public static void main(String[] args) { int a = 3; int b = 0; try{ System.out.println(a / b); int[] arr = {1, 2, 3, 4, 5}; System.out.println(arr[5]); }catch (ArithmeticException|ArrayIndexOutOfBoundsException a1){ System.out.println("发生异常"); } } }
注意:
- 不同的异常处理的方式是一样的,虽然简洁但是不能针对性的进行处理
- 多个异常的类型之间必须是平级的关系
package review.ExceptionDemo; public class demo8 { public static void main(String[] args) { int a = 10; int b = 0; try { System.out.println(a/b); }catch (ArithmeticException a1){ //方法一 String message = a1.getMessage(); //打印出现问题的原因 System.out.println(message); //方法二 String s = a1.toString(); System.out.println(s); //方法三 a1.printStackTrace(); } System.out.println("之后程序的代码正常执行"); } }
这里打印的异常信息,与没有做异常处理时,JVM自动在控制台给出的异常信息类似。但是做了异常处理后,可以让程序后面的代码正常的执行,不会因为这个异常而导致整个程序的终止。
这个方法是从java.lang.Throwable类继承过来的,会将具体的错误发生的栈轨迹信息打印在控制台上
package test.ExceptionDemo; public class ExceptionDemo3 { public static void test1() throws Exception{ throw new Exception("Exception"); } public static void test2() throws Exception{ test1(); } public static void main(String[] args) { try{ test2(); } catch(Exception e) { e.printStackTrace(); } } }
在方法test1()中抛出异常,方法test2()中调用方法test1(),在main方法中捕获异常,并且打印栈轨迹信息。因此,输出依次展示了test1() —> test2() —> main的过程。
throws有时候我们可以针对一些异常进行处理,但是也有的时候,我们无法处理这个异常
对于这种情况,为了保证程序的正常执行,可以使用try-catch-finally之外的第二个处理方法
throws抛出异常,用在方法的声明上,表明当前方法不处理异常,等实际调用的时候,由该方法的调用者来处理异常
格式:
throws 异常类名
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2 … { }
注意:
- 抛出编译时异常,抛出异常的方法内可以不做处理,但是调用该方法的时候必须做处理,否则编译时就会报错
- 抛出运行时异常,调用时可以不做任何处理。编译时不会报错,但是程序遇到错误会终止
- 最好抛出详细的异常类型,也可以抛出更大的异常类型,但是处理的时候要对应上。比如throws Exception,则catch语句中是 Exception e
- 尽量不要在main方法上抛出,如果在main方法上抛出,就会交给JVM处理,遇到异常时程序会直接停止
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class demo9 { public static void main(String[] args) { System.out.println("程序开始"); try { fun1(); }catch (Exception pe){ pe.printStackTrace(); } try { fun2(); }catch (ArithmeticException ae){ ae.printStackTrace(); } System.out.println("程序结束"); } public static void fun2() throws ArithmeticException{ int a = 10; int b =0; System.out.println(a/b); } public static void fun1() throws ParseException { String s = "2021-10-18"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = sdf.parse(s); System.out.println(date); } }
发生异常之外的代码都正常的执行了
throws和throw的区别:
- throws用来声明一个方法可能产生的所有异常,throw用来抛出一个具体的异常类型。
- throw语句用在方法体内,表示抛出异常,由方法体内的语句处理。
throws语句用在方法声明后面,表示抛出异常,由该方法的调用者来处理 - throws只是表明一种可能性,不一定会抛出异常
throw则是一定会抛出一个具体的异常
package review.ExceptionDemo; public class demo10 { public static void main(String[] args) { fun(); } public static void fun(){ int a = 10; int b = 0; if(b == 0){ System.out.println("报错,除数不能为0"); throw new ArithmeticException(); }else { System.out.println(a/b); } } }throws举例
package review.ExceptionDemo; public class demo10 { public static void main(String[] args) { try{ fun(); }catch(ArithmeticException ar){ ar.printStackTrace(); } System.out.println("程序结束"); } public static void fun() throws ArithmeticException{ int a = 10; int b = 0; System.out.println(a/b); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)