异常错误
目标:理解异常错误/用try catch取得异常错误的方法
本讲我们专门来讲一下异常错误。制作程序,最重要的就是没有错误,也就是没有bug。因此,我们就必须对异常错误有一个充分的认识。 | |
异常错误…挺起来很麻烦,异常是指什么? | |
呵呵,对于Java的学习,明白什么是异常是非常重要的。好,下面就让我来介绍一下吧。要好好听哦。 |
什么是异常
尼克,咱们刚才说的“异常”的意思你明白么,什么样的事情属于异常? | |
是的,博士!我认为一般来讲,异常就是“不同于寻常,不适用于普遍原则的事情”,对么? | |
没错。咱们一会儿看一下Java程序的范例。对于Java程序而言,所谓的异常就是指“Java程序里发生预料之外的错误,而使程序中止。” | |
哦,那在什么时候会发生异常呢? | |
什么样的异常都可能发生啊。比较有代表性的如,超出排列区域的值,找不到文件等。 |
简单的处理异常的方法
咱们先把以前学过的简单的处理异常的方法复习一下。 | |
好的,博士。恩…好像要使用try,catch… | |
是的。try,catch的写法如下。 |
try { // 发生异常的 code } catch (exception_type identifier){ // 异常发生时的处理 } |
我想起来了。try程序块中实际记载了发生异常的code,而在catch程序块中记载着异常发生时的处理。 | |
恩。这一次我们就异常发生的具体情况进行解说。 |
体验异常
1.被 0 除的除法
首先来运行一下下面的程序。 | |
好的,博士。 |
1
| import javax.microedition.midlet.MIDlet; | ||
2
| import javax.microedition.lcdui.Display; | ||
3
| |||
4
| |||
5
| public class ZeroException extends MIDlet{ | ||
6
| private Display display; | ||
7
| private final static int x = 0; | ||
8
| private final static int y = 1; | ||
9
| |||
10
| public ZeroException(){ | ||
11
| display = Display.getDisplay(this); | ||
12
| System.out.println(y / x); //被0除的除法 | ||
13
| } | ||
14
| public void startApp(){} | ||
15
| public void pauseApp(){} | ||
16
| public void destroyApp(boolean unconditional){} | ||
17
| } | ||
好了,开始运行… |
啊?编译没什么问题,但怎么还有错误发生啊… | |
这个就是异常。上面不是显示“Java.lang.Exception”么?这说明刚才的程序里面有错误。 | |
是这样啊。不过,这个提示画面里并没有显示异常是在哪里发生的? | |
是啊。这点很遗憾,N820的模拟器与Java Standard Edition不太一样,N820的显示结果比较笼统。如果用Java Standard Edition的话,会出现下面的结果。 |
java.lang.ArithmeticException: /by zero at Exception.A.<init>(A.java:22) at Exception.A.main(A.java.18) Exception in thread "main" |
这样就清楚了。可以看到22行程序含有可能发生ArithmeticException异常的语句。 | |
没错。但是,由于目前N820的模拟器无法显示清楚,就需要自己把发生异常的地方找出来了。不过这也是有窍门的,掌握之后就比较容易了。 | |
太好了,博士。 | |
先来仔细的看一下刚才的程序吧。刚才说运行时出现错误,然后发生异常。那我们就把其中可能生成异常的code找出来。 | |
恩…除了“ System.out.println(y / x); //被0除的除法”显得奇怪,其他都与平常一样啊… | |
恩。如果觉得奇怪,就先用try,catch来试一下吧。 | |
是,我明白了。是这样的吧? |
1
| import javax.microedition.midlet.MIDlet; | ||
2
| import javax.microedition.lcdui.Display; | ||
3
| |||
4
| |||
5
| public class ZeroException extends MIDlet{ | ||
6
| private Display display; | ||
7
| private final static int x = 0; | ||
8
| private final static int y = 1; | ||
9
| |||
10
| public ZeroException(){ | ||
11
| display = Display.getDisplay(this); | ||
12
| try{ | ||
13
| System.out.println(y / x); //被0除的除法 | ||
14
| }catch(Exception e){ | ||
15
| System.out.println(“catch!!!”); | ||
16
| e.printStackTrace(); | ||
17
| } | ||
18
| } | ||
19
| public void startApp(){} | ||
20 | public void pauseApp(){} | ||
21 | public void destroyApp(boolean unconditional){} | ||
22 | } | ||
恩,然后运行一下看看。如果try块里的code含有生成异常的程序,就会被e.printStackTrace()检验出异常结果。 |
啊,异常被捕获了! | |
没错。实际上这个程序是有错误的。int型变量是不能被0除的。看到提示控制画面显示java.lang.ArithmeticException异常发生在13行了吧。也就是说,ArithmeticException异常是算术计算中由于异常条件而产生的异常。 | |
是这样的。那么问题就可以解决了! | |
恩,是啊…还有一点,为了养成规规矩矩写程序的好习惯,最好把刚才的程序做如下的变更。 |
10
| public ZeroException(){ | ||
11
| display = Display.getDisplay(this); | ||
12
| try{ | ||
13
| System.out.println(y / x); //被0除的除法 | ||
14
| }catch(Exception e){ | ||
15
| System.out.println(“catch!!!”); | ||
16
| e.printStackTrace(); | ||
17
| } | ||
18
| } | ||
这样啊,但是博士,不能在整个catch块中使用(Exception e)么? | |
确实对于这个程序来说是没有问题的,但是,考虑到try块中可能发生复数的异常,最好就不要使用了。如果还想了解的更详细一些就自己去调查一下吧。 | |
是,博士。 |
2. 找不到文件
接下来,我们再看一个例子,参考下面程序。 | |
是,博士。 | |
这次来看看找不到程序时会发生什么样的异常吧。 |
1
| import javax.microedition.lcdui.Canvas; | ||
2
| import javax.microedition.lcdui.Display; | ||
3
| import javax.microedition.lcdui.Graphics; | ||
4
| import javax.microedition.midlet.MIDlet; | ||
5
| import javax.microedition.lcdui.Image; | ||
6
| |||
7
| /** | ||
8
| * graphic描画用模板 | ||
9
| */ | ||
10
| |||
11
| public class Sample extends MIDlet{ | ||
12
| private Display display; | ||
13
| private Canvas canvas; | ||
14
| |||
15
| public void startApp(){ | ||
16
| display = Display.getDisplay(this); | ||
17
| canvas = new TempleteCanvas(); //初始化canvas | ||
18
| display.setCurrent(canvas); //显示canvas | ||
19
| } | ||
20 | |||
21 | public void pauseApp(){} | ||
22 | public void destroyApp(boolean arg0){} | ||
23 | } | ||
24 | |||
25 | class TempleteCanvas extends Canvas{ | ||
26 | private Image image = null; | ||
27 | |||
28 | |||
29 | public TempleteCanvas(){ | ||
30 | image = Image.createImage("/hoge.png"); | ||
31 | } | ||
32 | public void paint(Graphics g){ | ||
33 | g.drawImage(image, 120, 127, Graphics.HCENTER|Graphics.VCENTER); | ||
34 | } | ||
35 | } | ||
这个程序是单纯显示图像的。有不明白的地方么? | |
以前我们不是写过类似的程序么?当然没有问题啦。 | |
这是故意获取不存在的文件,用来测试异常发生的程序。不要在Resource里加入“hoge.png”,编译后试着运行一下。 | |
好的!因为resource里面没有文件,所以会出现错误吧。 |
博士…编译好像通不过啊。 | |
恩,这就对了。像这样进行编译时,有时必须在发生异常的code里抛出异常,或者捕获异常才行。 | |
也就是说,30行有发生异常的code,使用try,catch命令就可以了吧? | |
对! |
29 | public TempleteCanvas(){ | ||
30 | try{ | ||
31 | image = Image.createImage("/hoge.png"); | ||
32 | }catch(Exception e){ | ||
33 | e.printStackTrace(); | ||
34 | } | ||
35 | } | ||
这样就对了吧? | |
恩,做的不错。这样一来,编译错误就不见了。 | |
好哇!那我们就来编译和运行吧! |
好了!编译通过了,下面是运行… |
博士!上面的错误出现了!当然画面上什么表示都没有。 | |
是的。因为指定了不存在的文件,所以发生了异常。 | |
但是这代表什么意思呢? | |
提示画面显示:java.io.IOException: Cannot find resource /hoge.png。这表明里面没有hoge.png文件。 | |
没错。因为是故意在没有文件的状态下进行编译的啊。同时也可以确认是30行出现了异常。 可是博士,这个Error: java.lang.NullPointerException: Image is null是什么意思呢? | |
是呀。这是程序欲使用null而导致的异常。这与最初的异常还不一样。是TempleteCanvas类捕获Image对象时产生了一个异常是吧?此时Image对象是null。 | |
啊,是这样啊。也就是说,然后在呼出paint方法时欲使用null的image对象而发生了异常。 | |
恩。没错。 |
•小结
本讲我们讲了异常错误,学得怎么样啊? | |
恩,异常错误有许多种的啊。 | |
本讲介绍的情况都是事前不知道异常的种类,而运行的例子。不管是什么情况,参考提示画面的说明很重要啊。 | |
是啊。这样我也学会异常错误发生时的调查方法了。 | |
是啊。对于Java而言,异常可是很深奥的东西。此外还有各种各样的功能呢。咱们刚才讲的异常只是其中的一个类型,还有许多别的,你去自己试着探索一下吧。 | |
好的,博士! |