java异常处理--用代码说话

来源:互联网 发布:abaqus软件介绍 编辑:程序博客网 时间:2024/05/21 09:03

1.基本概念

当出现程序无法控制的外部环境问题(如:用户提供的文件不存在,文件内容损坏,网络不可用)时,java就会用异常对象描述。


2.处理

java中使用两种方式来处理异常:

1>在发生异常的地方直接处理;

2>将异常抛给调用者,让调用者处理。


3.异常分类

1>检查性异常 java.lang.Exception

检查性异常:

程序是正确的,但因为外界的环境条件不满足而引发。比如,我晚上要去吃饭,结果,去了饭馆没开门,这是我的错吗?我吃饭(就类似于程序)有错吗?没错,只是外界条件不满足,所以这就是异常。在java中,比如,程序试图打开一个远程并不存在的Socket端口,或者打开不存在的文件时,这不是程序本身的逻辑错误,而很可能是远程机器名字错误,对商业软件系统,程序开发者必须考虑并处理这个问题,java编译器强制要求,处理这类异常类,如果不捕获这些异常,程序不能被编译。


我举一个实际案例来说明问题微笑

</pre><pre name="code" class="java">package com.test;import java.io.FileReader;import java.net.Socket;public class test3 {    public static void main(String[] args) {        //检查性异常,1.打开文件        FileReader fr=new FileReader("d:\\aa.text");       //2.连接一个192.168.1.23 ip的端口号78            }}

FileReader fr=new FileReader("d:\\aa.text");
这条语句会报错,

未报告的异常错误FileNotFoundException; 必须对其进行捕获或声明以便抛出
----

Socket s=new Socket("192.168.1.23", 78);

会报错:

未报告的异常错误UnknownHostException; 必须对其进行捕获或声明以便抛出----

就算你写的ip和端口都是对的,但是编译器认为你可能写错了。

所以,检查性异常就是编译器可以事先确认的异常。



2>运行期异常 java.lang.RuntimeException

运行时异常:

这意味着,程序存在bug,如:数组越界,0被除,入参不满足规范...........这类异常需要更改程序来避免。java编译器强制要求处理这类异常。

这类异常,编译通过,这一点上,编译器“并不是足够聪明”。所以,在运行的时候会出错。属于程序逻辑上出了错。一般比较难检查。


3>错误(最严重) java.lang.Error


错误:

       一般很少见,也很难通过程序解决。它可能源于程序的bug,但一般更可能源于环境问题,比如,内存耗尽,错误在程序中处理,

而由运行环境处理。



 java.lang.RuntimeException继承自 java.lang.Exception。

 java.lang.Error和 java.lang.RuntimeException继承自java.lang.Throwable类。

但是顶层类都是java.lang.Throwable



4.异常处理:

1>try.....catch

程序运行产生异常时,将从异常的发生点中断程序,并向外抛出异常信息。

package com.test;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.net.Socket;import java.util.logging.Level;import java.util.logging.Logger;public class test3 {    public static void main(String[] args) {        try {            //检查性异常,1.打开文件            FileReader fr=new FileReader("d:\\aa.text");            //2.连接一个192.168.12.12 ip的端口号4567             Socket s=new Socket("192.168.1.23", 78);        } catch (FileNotFoundException ex) {            Logger.getLogger(test3.class.getName()).log(Level.SEVERE, null, ex);        } catch (IOException ex) {            Logger.getLogger(test3.class.getName()).log(Level.SEVERE, null, ex);        }    }}

要做到最小捕获异常的原则。是在不知道,可以catch(Exception e),最大的。

捕获结果;

六月 11, 2015 9:47:34 下午 com.test.test3 main
严重: null
java.io.FileNotFoundException: d:\aa.text (设备未就绪。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at java.io.FileReader.<init>(FileReader.java:58)
at com.test.test3.main(test3.java:15)

因为第一个有异常,所以第二个就没机会捕获了,程序已经中断了,想要看到第二个catch的作用,那么我现在把第一个语句注释掉,再次捕获。再次修改代码!

package com.test;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.net.Socket;import java.util.logging.Level;import java.util.logging.Logger;public class test3 {    public static void main(String[] args) {        try {            //检查性异常,1.打开文件           // FileReader fr=new FileReader("d:\\aa.text");            //2.连接一个192.168.12.12 ip的端口号4567             Socket s=new Socket("192.168.1.23", 78);             System.out.println("connect success!");        } catch (FileNotFoundException ex) {            Logger.getLogger(test3.class.getName()).log(Level.SEVERE, null, ex);        } catch (IOException ex) {            Logger.getLogger(test3.class.getName()).log(Level.SEVERE, null, ex);        }        System.out.println("ok");    }}
运行结果:

java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at java.net.Socket.<init>(Socket.java:434)
at java.net.Socket.<init>(Socket.java:211)
at com.test.test3.main(test3.java:17)

ok

小结:再出现异常的地方,就终止执行代码,然后进入到catch,如果,你有多个catch语句,则进入匹配异常那个的catch。

2>finally

如果把finally块放在try......catch的语句后面,finally语句是不管catch语句块是否执行,一般都会执行的。

下面是非一般情况:

a.finally块中发生异常

b. 程序所在线程死亡

c.在前面的代码中有system.exit();语句

d. 关闭cpu

package com.test;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.net.Socket;import java.util.logging.Level;import java.util.logging.Logger;public class test3 {    public static void main(String[] args) {        FileReader fr=null;        try {            //检查性异常,1.打开文件            fr=new FileReader("H:\\aa.txt");            //2.连接一个192.168.12.12 ip的端口号4567            // Socket s=new Socket("192.168.1.23", 80);        } catch (FileNotFoundException ex) {            System.exit(-1);//finally就不会执行            Logger.getLogger(test3.class.getName()).log(Level.SEVERE, null, ex);        } catch (IOException ex) {            Logger.getLogger(test3.class.getName()).log(Level.SEVERE, null, ex);        }        finally{            System.out.println("进入finally语句块");            //这个语句块,不管有没有异常都会执行            //一般把需要关闭的资源,如文件,或者数据库的连接,开辟的一些内存等               if(fr!=null){                   try {                       fr.close();                   } catch (IOException ex) {                                ex.printStackTrace();                   }               }        }        System.out.println("ok");    }}


2>抛出异常,将异常抛给调用者,让调用者处理异常 throws

案例说明:

package com.test;import java.io.FileNotFoundException;import java.io.FileReader;import java.util.logging.Level;import java.util.logging.Logger;public class test {public static void main(String[] args) {                Father father=new Father();                father.test1();    }}class Father{    private Son son=null;    public Father(){        son=new Son();    }    public void test1(){        System.out.println("1");         //son.test2();//现在好了,儿子没有处理的异常抛给了父亲,父亲调用了儿子的方法,            //而throws语句,是抛给调用者的,所以,此时父亲有两种方法解决这个异常,            //一个是也不想管这个异常,往出抛,谁调用谁来处理这个异常,那么现在再            //往上抛就是JVM了,那好了, 既然是当父亲的,那么就管管吧,用try catch            //用throws的缺点就是,不知道异常出在了哪里        try {            son.test2();        } catch (FileNotFoundException ex) {            System.out.println("父亲在处理异常。");            ex.printStackTrace();        }    }}class Son{    public void test2() throws FileNotFoundException{        FileReader fr=null;        fr=new FileReader("d://aa.txt");//这个文件并不存在的    }}
输出结果:

1
父亲在处理异常。
java.io.FileNotFoundException: d:\aa.txt (设备未就绪。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at java.io.FileReader.<init>(FileReader.java:58)
at com.test.Son.test2(test.java:37)//真正的错误的根源在这一行
at com.test.Father.test1(test.java:27)//第27行在父亲类test1方法 里面调用了,
at com.test.test.main(test.java:11)//在主方法里面调用了

如果父亲也不管,都向上抛最后抛到主方法那里去,然后呢,Jvm处理,这样子做的效率并不高,不建议。建议,哪里出问题,就在哪里try catch。

就像下面这样的代码:不建议

package com.test;import java.io.FileNotFoundException;import java.io.FileReader;import java.util.logging.Level;import java.util.logging.Logger;public class test {public static void main(String[] args) throws FileNotFoundException {                Father father=new Father();                father.test1();    }}class Father{    private Son son=null;    public Father(){        son=new Son();    }    public void test1() throws FileNotFoundException{        System.out.println("1");         son.test2();//现在好了,儿子没有处理的异常抛给了父亲,父亲调用了儿子的方法,            //而throws语句,是抛给调用者的,所以,此时父亲有两种方法解决这个异常,            //一个是也不想管这个异常,往出抛,谁调用谁来处理这个异常,那么现在再            //往上抛就是JVM了,那好了, 既然是当父亲的,那么就管管吧,用try catch            //用throws的缺点就是,不知道异常出在了哪里//        try {//            son.test2();//        } catch (FileNotFoundException ex) {//            System.out.println("父亲在处理异常。");//            ex.printStackTrace();//        }    }}class Son{    public void test2() throws FileNotFoundException{        FileReader fr=null;        fr=new FileReader("d://aa.txt");    }}
运行结果:

1
Exception in thread "main" java.io.FileNotFoundException: d:\aa.txt (设备未就绪。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at java.io.FileReader.<init>(FileReader.java:58)
at com.test.Son.test2(test.java:37)
at com.test.Father.test1(test.java:21)
at com.test.test.main(test.java:11)
Java Result: 1













1 0