Java基础——异常(Exception)

来源:互联网 发布:好scratch编程 编辑:程序博客网 时间:2024/05/29 03:21

异常:程序运行时出现的非正常现象。

对异常的处理通常有两种方法:

系统检测到程序的错误,给出错误信息并终止程序的运行;
在程序中加入处理异常的功能。

ThrowableJava 语言中所有错误或异常的超类。
Java中,将异常情况分为ExceptionError两大类,因此有两种Throwable对象
Exception解决程序及环境产生的异常,可由程序捕获并处理
Error处理较少发生的内部系统错误,不能被程序捕获,只能由用户按照系统提示关闭程序。
异常类的名字就代表了可能发生的异常的含义。该类代表一类异常,某个异常类的对象代表真正所发生的异常。
异常并不都是在 java.lang包中定义,其它如util,net, io中均有定义。所有的I/O异常都继承自java.io.IOException
当一个Java程序违背了语义限制的时候,JVM会把这个错误看作一个exception.
比如除零异常。
那些在编译时能被检查的异常称为checked exceptions,其他为unchecked exceptions .
unchecked exceptions 类有两种:RuntimeException及它的子类、Error及它的子类 ,其它的异常类均为checked exception类。
异常对象代表所发生的异常,但不是异常本身
异常对象可能由系统被动产生,也可以由程序主动产生
Java语言中,异常机制是:一旦出现异常,可以由运行的方法(主动)JVM(被动)生成一个异常对象,它代表该异常事件的类型。异常对象从产生和被传递提交给Java运行系统的过程称为抛出异常(throw
你可以抛出任何类型的异常。
比如引用 t,在使用t之前,我们应该检查t是否真正地引用某个实例,如下:

if(t== null)

thrownew NullPointerException();//程序产生

所有异常类的构造方法有两类,一类是缺省构造方法,一类是带有字符串参数的构造方法:

thrownew NullPointerException("t= null");

throw new所产生的引用抛出,由catch捕获,进行处理。
当发生异常时,会有下面的过程:首先,创建(系统或程序)异常对象代表异常,然后当前的执行流程中断,异常处理机制接管并且寻找合适的代码以继续执行程序,这段代码就是exceptionhandler
如同生产线上,当某个产品被发现有某种缺陷时,会被质检员贴上某种描述该缺陷的标签(这个标签类比为异常对象),然后撤出该产品并根据标签的类别,该产品会被发送到不同的部门进行相应的处理(相当于是exceptionhandler)。
抛出的异常必须被处理,形式如下:

try{

//Code that might generate exceptions

}catch(Type1 id1) {

//Handle exceptions of Type1

}catch(Type2 id2) {

//Handle exceptions of Type2

}catch(Type3 id3) {

//Handle exceptions of Type3

}
有时候,不管try中有没有异常的发生都要执行一些特定的语句,那么这些语句可以放在finally语句中,如下:
try {
// The guarded region: Dangerousactivities
// that might throw A, B, or C
} catch(A a1) {
// Handler for situation A
} catch(B b1) {
// Handler for situation B
} catch(C c1) {
// Handler for situation C
} finally {
// Activities that happen everytime
}
finally语句块中的代码是一定会执行的。
只要在执行finally语句块之前退出了JVM,则finally语句块不会执行.
  try{
  //退出JVM
  System.exit(0);
  }finally{
  //不会执行.
  System.out.println("finally....");
  }
除了RuntimeException或者其子类的异常,所有的异常都应该被处理
方法内部如果产生异常,则该异常要么使用throw抛出异常,并结束方法的执行。要么在该方法内部通过try…catch进行处理,

try {

// 可能会产生异常的代码段

} catch(Type1 id1) {

// Handle exceptions ofType1

}

在方法内部如果产生异常但没有处理,则需要抛出异常,该方法需要使用异常表。
使用异常表指定某个方法可能抛出的异常的种类。使用方法如下:
void f() throws TooBig,TooSmall, DivZero {//...
下例
void f() { // ...
意味着该方法不会抛出任何异常 (除了RuntimeException异常或那些继承自的异常)
方法可能产生的所有异常,异常表中都应列出(除了RuntimeException异常或那些继承自的异常),但异常表中的出现的异常,方法中可以没有发生。
异常表中的异常必须处理!

所有RuntimeException类及其子类的异常均可以自动处理.
RuntimeException异常及子类异常无需出现在异常表中,而且这种异常既可以通过catch捕获,也可以不处理。
记住:你只能忽略RuntimeException(或它的子类)
JDK异常没有包括所有可能的异常情况,所以你可以写出自己定义的异常类来。
为创建自己的异常,你应该继承一个在意义上和该异常相似的异常类。

classSimpleExceptionextends Exception {}

publicclass SimpleExceptionDemo {

publicvoid f() throws SimpleException {

 System.out.println("ThrowSimpleException fromf()");

 throw new SimpleException();

}

publicstatic void main(String[] args) {

SimpleExceptionDemosed = newSimpleExceptionDemo();

try{

sed.f();

}catch(SimpleException e) {

System.err.println("Caughtit!");

}}}

class MyException extends Exception {

    public MyException() {}

    public MyException(Stringmsg) { super(msg); }

}

public class FullConstructors {

    public static voidf() throws MyException {

      System.out.println("ThrowingMyException fromf()");

      throw new MyException();

  }

    public static voidg() throws MyException {

      System.out.println("ThrowingMyException fromg()");

      throw new MyException("Originated ing()");

  }

    public static voidmain(String[] args) {

      try {

        f();

      } catch(MyException e) {

        System.out.println(e);

      }

      try {

        g();

      } catch(MyException e) {

        System.out.println(e);

      }    }}

当一个异常抛出以后,异常处理就近匹配。
继承类的异常会匹配基类的异常处理。

class Annoyance extends Exception {}

class Sneeze extends Annoyance {}

public class Human {

publicstatic void main(String[] args) {

try{

thrownew Sneeze();

}catch(Sneeze s) {

System.err.println("CaughtSneeze");

}catch(Annoyance a) {

System.err.println("CaughtAnnoyance");

}}}


catch(Exceptione) {
System.err.println("Caughtan exception");
}
上面的catch可以捕获任何类型的异常,所以,上面的语句应该放在异常处理语句的最后。
finally语句块是一定会执行的,所以通常在程序中为了保证某资源一定会释放,所以一般在finally语句块中释放资源。*/
import java.io.*;
public class ExceptionTest10{
  public static voidmain(String[] arg){
  //必须在外边声明
  FileInputStreamfis = null;
  try{
  fis = newFileInputStream("ExceptionTest10.java");
  }catch(FileNotFoundException e){
  e.printStackTrace();
  }finally{
  //为了保证资源一定会释放.
  if(fis!=null){
  try{
  fis.close();
  }catch(IOException e){
  e.printStackTrace();
  }  } }  }}
/*
  重写的方法不能比被重写的方法抛出更宽泛的异常.
*/
import java.io.*;
/*
class A{
  public void m1(){}
}
class B extends A{
  //子类永远无法抛出比父类更多的异常.
  public void m1()throws Exception{}
}
*/
class A{
  //public void m1()throws FileNotFoundException{}
  public void m1()throws IOException{}
}
class B extends A{
  //public void m1()throws IOException{}
  public void m1()throws FileNotFoundException{}
}