异常:
1,异常:简单的说,能够产生使程序终止的行为。
2,异常的种类:
运行时异常:编译没问题,代码的问题,可以通过try{}catch(){}找到并且解决。
编译时异常:资源问题,不要让资源问题对代码产生异常。
Java规定:对于可查异常必须捕捉、或者声明抛出。可查异常一般为java编译器就可以查出来的异常。
如:
明明文件存在为什么会编译不通过呢?
编译器检查代码的时候发现这个代码有可能会因为资源问题会终止程序。所以必须要声明不处理异常,或者加上try{}catch(){}块中。
RuntimeException(修改代码解决)
ArithmeticException:数学计算异常
NullPointerException:空指针异常
NegativeArraySizeException:负数组长度异常
ArrayIndexOutOfBoundsException:数组索引越界异常
ClassNotFoundException:类文件未找到异常
ClassCastException:造型异常
IOException
FileNotFoundException:文件未找到异常
EOFException:读写文件异常
MalformedURLException:URL格式错误异常
SocketException:Socket异常
理解:异常可以通过程序修改处理,但是错误无法通过程序本身处理。
Throwable类的一些常用API:
1. 返回异常发生时的详细信息
public string getMessage();
2. 在控制台上打印Throwable对象封装的异常信息
public void printStackTrace();
import java.io.*;class MyDivideException extends ArithmeticException{ public MyDivideException(){ //super(); } public MyDivideException(String msg){ super(msg); } /*public String toString() { return "除以零引起的例外!"; }*/}public class DivideExceptionTest { public static void main(String args[]){ double n=20,d=0.0; double q=0; try{ if(d==0.0) throw new MyDivideException("除数不能为零"); System.out.println(n+"/"+d+"="+n/d); } catch(MyDivideException e){ //System.out.println(e.getMessage());//除数不能为零 //System.out.println(e); //覆写了toString输出:异常类加信息 //MyDivideException: 除数不能为零 e.printStackTrace(); //首先调用toString,之后再输出异常出现的位置如下: //MyDivideException: 除数不能为零 //at DivideExceptionTest.main(DivideExceptionTest.java:26) } } }
e.printStackTrace()的使用:
3,java对异常的处理机制:
nJava程序的执行过程中如出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统,这个过程称为抛出(throw)异常,抛出这个异常说明这个程序说明了不处理这个异常。
n当Java运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程称为捕获(catch)异常。
n如果Java运行时系统找不到可以捕获异常的方法,则运行时系统将终止,相应的Java程序也将退出。
n程序员通常只能处理异常(Exception),而对错误(Error)无能为力。
2. 应该在声明方法抛出异常还是在方法中捕获异常?
答:捕捉并处理知道如何处理的异常,而抛出不知道如何处理的异常。
异常处理中的关键字:
throws(可以声明一个或者多个异常,子类不能声明抛出比父类更多的异常):表示不处理这个异常或多个异常。就像:饭店,请保管好自己贵重物品,本店概不负责。
throw:方法内声明的异常,只可以抛出一个异常对象,表明他抛出了一个异常(程序会在throw语句后立即终止,它后面的语句执行不到)方法内抛出这个异常交给JRE,
①,JRE发现这个方法throws了这种异常,也就是说JRE知道这个方法不处理这异常,所以再次把这个异常抛给调用这个方法的对象来处理,这个对象通过try{}catch(){}来处理异常。如果也没有被trycatch块处理,这个时候就会把这个异常抛给JVM,这个时候程序就会终止。
②,JRE发现这个方法没有throws这种异常,这个时候又没有trycatch块处理这个异常,这是不可行的,个时候就会把这个异常抛给JVM,这个时候程序就会终止。
try catch:只有放在try块里面的代码,一旦产生异常才会被catch捕获。一旦try里面的代码产生异常,接下来try里面其他的代码将不会再执行,所以try里面的代码不能太大。catch处理完之后,catch之后的语句继续执行。
catch块呈正三角形或者金字塔型,从上往下处理异常的范围逐渐扩大,如果范围大的catch块在前面当捕获到异常的时候,之后的那个小范围的catch块原先也可以捕获到,但是这个时候异常被大范围的catch块捕获了,小范围ie的catch块就不会执行了,这个时候就会报错,所以catch块一定要呈金字塔或正三角形。
例:
RuntimeException异常类包括运行时各种常见的异常,ArithmeticException类和ArrayIndexOutOfBoundsException类都是它的子类。因此,RuntimeException异常类的catch子句应该放在 最后面,否则可能会屏蔽其后的特定异常处理或引起编译错误。
在块try{ }之间的为局部变量,在{}之外就释放掉了。
使用finally块释放资源
finally关键字表明:无论以任何方式离开try块,finally块里的语句都会被执行。
try在返回之前一定会执行finally里面的语句 所以一定不要在finally中加return,否则try语句块中的返回值就会被覆盖掉。
上代码:
try、catch、finally语句块的执行顺序:
1)当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句;
2)当try捕获到异常,catch语句块里没有处理此异常的情况:此异常将会抛给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行;
3)当try捕获到异常,catch语句块里有处理此异常的情况:在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句。
异常的隐藏:
如果catch中也抛出了异常,由于先执行的是try中的异常,然后catc中的异常抛出,导致了之后捕获的异常是catch中的异常,所以这就导致了try中的异常的隐藏。
异常的丢失:
finally中如果有返回值,JAVA异常处理机制在离开try语句之前都会去执行finally块。这个时候,如果finally块中有返回值,则程序不会再执行下去了,这个时候外部返回的就是finally中的返回值了,并不是try语句块中的异常。所以这就导致了try中的异常的丢失。
上代码:
自己定义异常:
结构:
detail message :私有的,通过构造方法设值。
自定义异常:
抛出异常可以用来提示用户:
getMessage()
异常处理的原则:
最好在注释里声明不处理那些异常。
方法内部不要抛出运行异常,
try一定要放容易产生异常的代码,而且try块不要太大,
不要用一个catch完成对所有异常的处理,应该定义多的,逐个对应相应的异常。
既然要catch拦截,一定要处理异常。
finally里面不要写return,容易丢失异常。
总的处理原则:
通过异常处理机制找到运行异常问题,并且解决问题。
对编译异常要进行预先的处理:最好抛出异常。