Java基础(55):Exception类详解(转)

             Java中的异常 Exception

java.lang.Exception类是Java中所有异常的直接或间接父类。即Exception类是所有异常的根类。

  比如程序:

 1 public class ExceptionTest
 2 {
 3       public static void main(String[] args)
 4       {
 5              int a = 3;
 6              int b = 0;
 7              int c = a / b;
 8              System.out.println(c);
 9       }
10 }

编译通过,执行时结果:

  Exception in thread "main" java.lang.ArithmeticException: / by zero

  at com.learnjava.exception.ExceptionTest.main(ExceptionTest.java:9)

  因为除数为0,所以引发了算数异常。

比较常见的异常还有这种:空指针异常

  java.lang.NullPointerException是空指针异常,出现该异常的原因在于某个引用为null,但却调用了它的某个方法,这时就会出现该异常。

Java中的异常分为两大类:

  1.Checked Exception(非Runtime Exception

  2.Unchecked ExceptionRuntime Exception

运行时异常

  RuntimeException类是Exception类的子类,它叫做运行时异常,Java中的所有运行时异常都会直接或者间接地继承自RuntimeException类。

  Java中凡是继承自Exception,而不继承自RuntimeException类的异常都是非运行时异常

异常处理的一般结构

 1 try
 2     {
 3          // 可能发生异常的代码
 4         // 如果发生了异常,那么异常之后的代码都不会被执行
 5     }
 6     catch (Exception e)
 7     {
 8         // 异常处理代码
 9     }
10     finally
11     {
12         // 不管有没有发生异常,finally语句块都会被执行
13     }

比如本文最开始的除法运算代码,加入异常处理之后:

 1 public class ExceptionTest
 2 {
 3     public static void main(String[] args)
 4     {
 5         int c = 0;
 6         try
 7         {
 8             int a = 3;
 9             int b = 0;
10
11             // 这块代码出现了异常
12             c = a / b;
13
14             // 那么异常之后的代码都不会被执行
15             System.out.println("Hello World");
16         }
17         catch (ArithmeticException e)
18         {
19             e.printStackTrace();
20         }
21         finally
22         {
23             //不管有没有发生异常,finally语句块都会被执行
24             System.out.println("Welcome");
25         }
26
27         System.out.println(c);
28         // 当b为0时,有异常,输出为c的初始值0
29     }
30 }

多个catch

  一个try后面可以跟多个catch,但不管多少个,最多只会有一个catch块被执行。

异常处理方法

一.对于非运行时异常(checked exception),必须要对其进行处理,否则无法通过编译。

  处理方式有两种:

  1.使用try..catch..finally进行捕获;

  2.在产生异常的方法声明后面写上throws 某一个Exception类型,如throws Exception,将异常抛出到外面一层去。

  对非运行时异常的处理详见代码例子:

  处理方式1:将异常捕获

 1 将异常捕获
 2
 3 public class ExceptionTest2
 4 {
 5     public void method() throws Exception // 将异常抛出,由调用这个方法的方法去处理这个异常,如果main方法也将异常抛出,则交给Java虚拟机来处理
 6     {
 7         System.out.println("Hello World");
 8
 9         // 抛出异常
10         throw new Exception();
11     }
12
13     public static void main(String[] args)
14     {
15         ExceptionTest2 test = new ExceptionTest2();
16
17         try
18         {
19             test.method();
20         }
21         catch (Exception e)
22         {
23             e.printStackTrace();
24         }
25         finally
26         {
27             System.out.println("Welcome");
28         }
29
30
31     }
32
33 }

    处理方式2:将异常继续向外抛出

 1 将异常抛出
 2
 3 public class ExceptionTest2
 4 {
 5     public void method() throws Exception // 将异常抛出,由调用这个方法的方法去处理这个异常,如果main方法也将异常抛出,则交给Java虚拟机来处理
 6     {
 7         System.out.println("Hello World");
 8
 9         // 抛出异常
10         throw new Exception();
11     }
12
13     public static void main(String[] args) throws Exception // main方法选择将异常继续抛出
14     {
15         ExceptionTest2 test = new ExceptionTest2();
16
17         test.method(); // main方法需要对异常进行处理
18
19         // 执行结果:
20         // Hello World
21         // Exception in thread "main" java.lang.Exception
22         // at com.learnjava.exception.ExceptionTest2.method(ExceptionTest2.java:10)
23         // at com.learnjava.exception.ExceptionTest2.main(ExceptionTest2.java:17)
24     }
25
26 }

对于运行时异常(runtime exception),可以对其进行处理,也可以不处理。推荐不对运行时异常进行处理。

自定义异常

  所谓自定义异常,通常就是定义一个类,去继承Exception类或者它的子类。因为异常必须直接或者间接地继承自Exception类。

  通常情况下,会直接继承自Exception类,一般不会继承某个运行时的异常类。

  自定义异常可以用于处理用户登录错误,用户输入错误提示等。

  自定义异常的例子:

  自定义一个异常类型

 1 public class MyException extends Exception
 2 {
 3     public MyException()
 4     {
 5         super();//继承父类的默认构造函数
 6     }
 7     public MyException(String message)
 8     {
 9         super(message);
10     }
11 }

一种异常处理方式:

 1 一种异常处理方式
 2
 3 public class ExceptionTest4
 4 {
 5
 6     public void method(String str) throws MyException
 7     {
 8         if(null == str)
 9         {
10             throw new MyException("传入的字符串参数不能为null!");
11         }
12         else
13         {
14             System.out.println(str);
15         }
16     }
17
18     public static void main(String[] args) throws MyException //异常处理方式1,不断向外抛出
19     {
20         ExceptionTest4 test = new ExceptionTest4();
21         test.method(null);
22     }
23 }

另一种异常处理方式(更常用):

 1 异常处理方式二
 2
 3 public class ExceptionTest4
 4 {
 5
 6     public void method(String str) throws MyException
 7     {
 8         if (null == str)
 9         {
10             throw new MyException("传入的字符串参数不能为null!");
11         }
12         else
13         {
14             System.out.println(str);
15         }
16     }
17
18     public static void main(String[] args)
19     {
20         //异常处理方式2,采用try...catch语句
21         try
22         {
23             ExceptionTest4 test = new ExceptionTest4();
24             test.method(null);
25
26         }
27         catch (MyException e)
28         {
29             e.printStackTrace();
30         }
31         finally
32         {
33             System.out.println("程序处理完毕");
34         }
35
36     }
37 }

前面说过,可以有多个catch块,去捕获不同的异常,真正执行的时候最多只进入一个catch块

  下面这个例子,定义了两种自定义的异常类型:

 1 多种异常
 2
 3 public class MyException extends Exception
 4 {
 5
 6     public MyException()
 7     {
 8         super();
 9     }
10
11     public MyException(String message)
12     {
13         super(message);
14     }
15 }
16
17
18 public class MyException2 extends Exception
19 {
20     public MyException2()
21     {
22         super();
23     }
24     public MyException2(String message)
25     {
26         super(message);
27     }
28
29 }
30
31
32 public class ExceptionTest4
33 {
34
35     public void method(String str) throws MyException, MyException2
36     {
37         if (null == str)
38         {
39             throw new MyException("传入的字符串参数不能为null!");
40         }
41         else if ("hello".equals(str))
42         {
43             throw new MyException2("传入的字符串不能为hello");
44         }
45         else
46         {
47             System.out.println(str);
48         }
49     }
50
51     public static void main(String[] args)
52     {
53         // 异常处理方式2,采用try...catch语句
54         try
55         {
56             ExceptionTest4 test = new ExceptionTest4();
57             test.method(null);
58
59         }
60         catch (MyException e)
61         {
62             System.out.println("进入到MyException catch块");
63             e.printStackTrace();
64         }
65         catch (MyException2 e)
66         {
67             System.out.println("进入到MyException2 catch块");
68             e.printStackTrace();
69         }
70         finally
71         {
72             System.out.println("程序处理完毕");
73         }
74
75     }
76 }

我们可以使用多个catch块来捕获异常,这时需要将父类型的catch块放到子类型的catch块之后,这样才能保证后续的catch块可能被执行,否则子类型的catch块将永远无法到达,Java编译器会报错。

  如果异常类型是独立的,那么它们的前后顺序没有要求。

  如对上面的代码进行改动后,如下列出:

 1 多个catch语句块的顺序
 2
 3 public class ExceptionTest4
 4 {
 5
 6     public void method(String str) throws Exception // 也可以声明Exception,只要声明的可以涵盖所有抛出的异常即可
 7     {
 8         if (null == str)
 9         {
10             throw new MyException("传入的字符串参数不能为null!");
11         }
12         else if ("hello".equals(str))
13         {
14             throw new MyException2("传入的字符串不能为hello");
15         }
16         else
17         {
18             System.out.println(str);
19         }
20     }
21
22     public static void main(String[] args)
23     {
24         // 异常处理方式2,采用try...catch语句
25         try
26         {
27             ExceptionTest4 test = new ExceptionTest4();
28             test.method(null);
29
30         }
31         catch (MyException e)
32         {
33             System.out.println("进入到MyException catch块");
34             e.printStackTrace();
35         }
36         catch (MyException2 e)
37         {
38             System.out.println("进入到MyException2 catch块");
39             e.printStackTrace();
40         }
41         catch (Exception e)
42         {
43             //虽然需要加上,但是这块代码不会被执行,只是为了编译成功
44             System.out.println("进入到MyException catch块");
45             e.printStackTrace();
46             //如果去掉前面两个catch块或其中之一,则发生该异常时就会进入此catch块
47             //catch块的匹配是按照从上到下的顺序,所以这个块如果放在最前面就会捕获所有的异常,后面的块永远不会执行,这时候会提示编译错误
48         }
49         finally
50         {
51             System.out.println("程序处理完毕");
52         }
53
54     }
55 }

面试常考题型

  try块中的退出语句

  虽然实际开发中不会遇到这样的情况,但是笔试面试时有关异常经常会问到如下情况:

 1 笔试面试题解析
 2
 3 public class ExceptionTest5
 4 {
 5
 6     public void method()
 7     {
 8         try
 9         {
10             System.out.println("进入到try块");
11
12             //return;
13             //会先执行finally块再返回
14
15             //虚拟机退出
16             //System.exit(0);
17             //不会执行finally块中的语句,直接退出
18         }
19         catch (Exception e)
20         {
21             System.out.println("异常发生了!");
22
23         }
24         finally
25         {
26             System.out.println("进入到finally块");
27
28         }
29
30         System.out.println("后续代码");
31
32     }
33
34     public static void main(String[] args)
35     {
36         ExceptionTest5 test = new ExceptionTest5();
37         test.method();
38     }
39 }

在加上return语句前,程序输出:

    进入到try块

    进入到finally块

    后续代码

如果在try块中加入return语句:

  程序执行输出:

    进入到try块

    进入到finally块

说明try块中有return语句时,仍然会首先执行finally块中的语句,然后方法再返回。

  如果try块中存在System.exit(0);语句,那么就不会执行finally块中的代码,因为System.exit(0)会终止当前运行的Java虚拟机,程序会在虚拟机终止前结束执行。

时间: 2024-10-02 06:30:44

Java基础(55):Exception类详解(转)的相关文章

Java基础之hashCode方法详解

想要明白hashCode的作用,必须要先知道java中的集合.(不明白的请看Java基础之集合框架详解(二)List篇和Java基础之集合框架详解(三)Set篇) Java中的Collection集合有两类,一类是List,另一类是Set,前者集合内的元素是有序的,元素可以重复:后者元素无序且元素不可重复.而我们通常使用Object.equals方法来判断两个元素是否重复.即当我们想查找一个元素中是否包含某个对象时,就是逐一取出每个元素与要找的元素进行比较,当发现某个元素与要查找的对象进行equ

java基础之HTTP协议详解

关于本文,是听了某个老师的课程之后倍感自己对HTTP了解不够深入,因此决定写此博文. 首先,可以参考此文:http://blog.csdn.net/gueter/article/details/1524447 第一部分:浏览器与服务器通信过程: 第二部分:HTTP请求介绍: 第三部分:HTTP协议响应 java基础之HTTP协议详解

Java基础与案例开发详解の常用类的介绍

String类 String类的常用构造方法 String s1 = new String(); String s2 = new String("hello"); String s3 = new String(char tmp[]); String s4 = new String(char[] value,int offset,int count) 除了以上方法构造String对象之外,Java编译器会自动为每一个字符串常量生成一个String 类的实例,因此字符串常量String有一

jdk1.8 java.util.stream.Stream类 详解

为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream.Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggregate operation),或者大批量数据操作 (

JAVA基础汇总及例题详解

java语言的一个核心: jdk, java development kits---面向开发人员 jre, java Runtime Environment---服务器上 java虚拟机---(以字节码为指令的CPU)---*.class java编译器-->字节码-->类加载器进行验证-->虚拟机运行 垃圾回收机制 public class ...{ int a = 1; } c/c++垃圾回收由程序员去运行 java编程语言(一门纯面向对象)的特点: 1, 面向对象  封装  继承

Java基础(44):ArrayList使用详解

1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处:    a.动态的增加和减少元素    b.实现了ICollection和IList接口    c.灵活的设置数组的大小 2.如何使用ArrayList 最简单的例子: ArrayList List = new ArrayList(); for( int i=0;i <10;i++ ) //给数组增加10个Int元素 List.Add(i); //..程序做一

【56】java本地文件File类详解

1.java类的介绍 public class File extends Object implements Serializable, Comparable<File> 文件和目录路径名的抽象表示形式. File既可以表示文件也可以表示目录. 用户界面和操作系统使用与系统相关的路径名字符串 来命名文件和目录.此类呈现分层路径名的一个抽象的.与系统无关的视图. 2.构造方法 File(File parent, String child) 根据 parent 抽象路径名和 child 路径名字符

java笔记之图形类详解

软件的交互方式:1. 控制台的交互方式.2. 图形化界面的交互方式 . java使用到的图形类主要在java.awt 与javax.swing包中. java.awt 与 javax.swing包的区别:java.awt中使用的图形类都是依赖于系统 的图形库的.javax.swing包使用到的图形类都是sun自己实现,不需要依赖系统的图形库.疑问: 既然swing包中的图形类已经取代awt包的图形类,为什么不删除awt呢? 1.swing比awt包出现的晚,所以会存在一些界面是用了awt包的相关

Java基础之集合框架详解(三)Set篇

相关定义 作为Collection接口的重要子接口,Set接口是一个不包含重复元素,且元素排列无序的集合,也被称为集. 注意:不包含重复元素的含义,更确切的讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素. Set接口的方法和Collection接口的方法大体相同,也就是说Set接口不像List接口那样可以通过索引或去元素,只能通过Iterator()方法获取迭代器进行迭代. Set中的add方法不同于Collection接口,有一个