标签:
1、异常概述:
什么是异常?
异常是一个类,用来描述程序运行时出现的不正常现象。
异常的由来:
异常源于现实生活中对于问题的描述,现实生活中的问题也是事物,问题也具有众多属性和行为,比如问题名称、
问题信息、问题原因、问题情况等。所以问题也可以被描述,并封装成对象。而现实生活中具有很多很多具体的问题,
这些问题有共性之处,也有不同之处,所以向上抽取,就会形成一个体系。
JAVA中用这样的一个体系来描述现实生活中问题的体系:
Object
|--Throwable
|---Error
|----OutOfMemoryError,..Error,...
|---Exception
|----RuntimeException,...
|-----IndexOutofBoundsException,NullPointerException,AritchmeticException,...
|------ArrayIndexOutofBoundsException,...
总体来讲:Trowable是祖先,下面分为两大派系:Error和Exception
Error:用来描述严重问题,所谓严重问题,就是不需要针对性处理的问题,因为非常严重,所以直接将
程序停掉,不要再继续执行就是对其的一般处理方式,并不需要将问题针对想处理完后,再继续运
行程序。
Exception:用来描述非严重问题,这类问题一般需要进行针对性处理,即程序员需要在程序中用代码处理,
如果交给JVM处理的话,JVM会直接停掉程序,然后将异常对象(即对出现的问题进行封装成的对象)抛出。
处理的一般格式是:
try{可能出现问题,即抛出异常对象的代码段}
catch(异常类 变量名){对()内指定的异常进行针对性的处理}
finally{不管抛出异常与否,都需要执行的部分}
注意:Exception和Error类都有很多子类,这些子类在命名时,JAVA都会使得其名称最后一部分是父类的
名称,即要么是Exception,要么是Error。
在学习这个体系的时候,需要查看JAVA API帮助文档,学习使用的原则是:查看父类定义,创建子类对象。
注意:程序中的异常是在程序运行时才会产生的,且异常产生的形式是生成异常对象,而异常对象的产生
有两种,一种是自动产生,一种是手动产生,手动产生为 "throw new 异常类名();",与产生普通类
对象一样,只是需要用关键字throw手动抛出。
而一旦抛出了异常对象后,程序就会发生跳转,即不再执行抛出异常对象语句以下的其他代码,跳转
到上一个调用者,并同时将异常对象抛给上一个调用者。若上层调用者没有相应的对其处理则继续抛出
到上一个调用者,直至抛到最上层的调用者JVM,JVM会对抛出的异常进行默认处理,即调用其内的默认
异常处理机制进行默认处理(实际上就是打印该异常对象的堆栈跟踪信息,即e.printStackTrace()。
)。然后结束整个程序。
通常对于被调用者抛给调用者的异常对象,调用者有两种方式进行处理,一种是不处理,继续向
上层调用者抛出,另一种是用try...catch语句处理。
2、try-catch: try..catch..它们是一个整体。可以没有finally块。
try{可能出现问题,即抛出异常对象的代码段}
catch(异常类 变量名){对()内指定的异常进行针对性的处理}
finally{不管抛出异常与否,都需要执行的部分}
try代码块用于检测是否有异常对象抛出,catch用于捕捉抛出的异常对象。
可以有多个catch代码块,当有多个catch代码块时,会依次匹配()中的异常类引用,看是否能将抛出的异常对象
转换成()中所示的异常类类型,即 “异常对象 instanceof 异常类”,如果该异常对象(暂时记为 ex )若能
赋给catch括号()中的 e ,则就执行catch大括号{}中的代码,执行完后,继续执行try..catch..finally中的
finally{}中的语句,执行完后,就继续执行下面的代码。其他的catch块就不再执行。如果不能赋给e,则继续
尝试赋值给下一个catch块中的e,直到匹配正确或匹配结束,如果匹配结束仍没有匹配到合适的e,则会默认
继续向上层抛出。
当出现自动抛出的异常对象后,如果没有相应处理,则该异常会抛到上一层调用者,上一层调用者没有处理或者
没能用catch捕获该异常,则该异常会继续抛到上一层调用者,直到被JVM处理,这种情况,程序就会发生连续跳转。
try
{
int a=3,b=0;
int x = a/b;
System.out.println("x = "+x);
}
catch(ArithmeticException e)
{
System.out.println(e.toString())
}
catch(NullPointerException e)
{
System.out.println(e.toString())
}
finally
{
}
注意:如果没有异常抛出,try块中没有异常对象出现,则就正常执行try块中的语句,不执行catch块中的
语句,如果有finally块,则执行finally块,然后继续执行其他语句。
3、异常声明throws:
异常声明:异常声明是指一个方法,对于自身的函数语句是否会产生异常并不确定,这时候,就可以在方法头的后面
用关键字throws声明可能产生的异常对象的类型(即其所属的类)。
目的:使用异常声明是为了告诉调用者,本函数可能会因为某些原因抛出一些异常,调用者需要做好准备有相应的
处理措施(要么继续抛出异常,即调用者也在函数头声明异常,要么使用try..catch..语句处理异常)。
而一旦一个方法进行了异常声明后,则其调用者必须用try..catch..处理可能被抛出的异常对象(即用try块检测
可能抛出异常的这个方法的调用部分),或者继续向上抛出异常(即也进行异常声明)。
特殊情况:当一个函数内进行了手动抛出异常对象,即throw new 异常类(); ,则就需要将该函数进行该异常类
声明,即用throws 异常类,放在函数的()和{}之间的位置上。这是强制的,否则编译会报错。这种情况,只
针对“编译时异常”有约束作用,对于“运行时异常”(即RuntimeException及其子类)没有约束作用,在7中会
详述。
eg.
class B
{
public void method(int a,int b) throws XXException,YYException
{
if(b == 1)
throw new XXException();
if(a < b)
throw new YYException;
return a*b;
}
}
class A
{
public static void main()
{
B b = new B();
try //定义在其中的变量时局部变量,只在try代码块中有效。所以要注意变量的作用域。
{
int x =b.method(3,1);
System.out.println(x);
}
catch(XXException e)//这里的定义类似于函数,e是一个局部变量,只在该catch块中有效。
{
System.out.println(XX);
}
catch(YYException e) //这些代码块中可以有各种语句,定义很多东西,内部类,变量,对象都行。
{
System.out.println(YY);
}
System.out.println("over!");
}
}
4、多异常处理:当一个try块对应多个catch块时,即有多个异常对象要处理时,异常对象应按照下面的规则进行处理:
父类的异常对象要放在子类的异常对象的下面。否则编译会报错,因为子类异常对象处理代码时永远也
执行不到的。
同时一个方法可以抛出多个异常对象,但是一次只能抛出一个异常对象,不会同时抛出两个异常对象
的,该方法可以进行多个异常类的声明,用逗号隔开,即throws XXException,YYException,ZZException
5、自定义异常:
自定义异常需求:当项目中出现需要本项目特有的问题时,JAVA中没有对其进行描述过,所以需要自己对该
问题进行描述,这是就需要自定义自己的异常类。
自定义异常:一个类需要加入到JAVA异常体系中,才能成为自定义异常类。一般通过继承Exception类或者
RuntimeException类来完成。这个自定义的异常类中可以覆写父类中的方法,也可以定义自己特有的数据和
成员。
对于是继承Exception还是RuntimeException呢?
如果自定义异常类是编译时异常,则继承Exception类。
如果自定义异常类是运行时异常,则继承RuntimeException类。
如何判断自定义异常类是不是编译时异常,请看7。
6、throw和throws的区别:
throws关键字用在函数上,用来进行异常类声明。其后面跟着的是异常类名称,可以跟多个,用逗号分隔
throw关键字用在函数内,用来抛出异常对象。其后面跟的是一个异常类对象,只能一个。
7、RuntimeException:
什么是运行时异常和编译时异常?
异常分为两种,一种是编译时异常,一种是运行时异常。
编译时异常是编译时检测的异常,该种异常是指该异常对象出现时,并不会完全影响到运算,处理完该
异常后,仍然可以继续运行程序的。
运行时异常是编译时不检测的异常,该种异常是指该异常对象出现时,代表者不能进行运算了,所以该
异常对象代表运算不能进行了,所以其后面的哪些可能基于该运算的语句都不应该继续运行下去了。
整个程序也不应该继续运行下去了,应当对代码进行修正,已达到可以正确运算的目的。所以当出现
该异常时,JVM希望程序终止,不要再运行下去了,如果对该类异常处理后,使得程序继续运行下去
就相当于隐藏了情况,使得我们无法知道程序出现的是什么问题,如果是运算问题,就应该停止执行
,修正代码。比如空指针异常(NullPointerException)、算数异常(ArithmeticException)除数为
0。说明调用方式出现了问题,并没有正确提供正确运算的参数,需要修正代码。
编译时异常,是在程序中出现该异常时,可以针对性处理后,程序仍继续执行。
运行时异常,是在程序中出现该异常时,希望不对该异常进行处理,希望程序要停止,使得程序员发现问题,
并进行代码修改。
所以:如果在函数内有抛出编译时异常对象,则函数上必须进行该异常类的声明。否则编译出错,而且
调用者必须由相应的处理操作(继续抛出或者try处理),否则编译出错。
如果在函数内有抛出运行时异常对象,则函数上不必进行该异常类的声明(声明编译也是对的,但一般
不声明),调用者也不必进行处理操作(操作也是对的,但一般不操作),编译一样会通过。而运行时
异常类就是指RuntimeException及其子类。
*/
class Demo
{
int x =0;
int div(int a,int b)
{
int[] arr = new int[5];
System.out.println(arr[a]);
return a/b;
}
void Print(String str)throws ArithmeticException,NullPointerException
{
try
{
if(str.equals("wanglinlin"))
{
String info = "Failure!没有捕获到--div--抛出的异常";
try
{
System.out.println(str+div(4,0));
}
catch (ArithmeticException e)
{
info ="Success!成功捕获到--div--抛出的异常";
System.out.println(e.getMessage());
}
finally
{
System.out.println("Print Finally:"+info);
}
}
}
catch (NullPointerException e)
{
System.out.println(e.getMessage());
}
}
}
class ExceptionDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x=d.div(4,1);
System.out.println("x ="+x);
}
catch (NullPointerException e)//此处相当于多态 Exception e = new ArithmeticException();
{
System.out.println("除数为0");
System.out.println(e.toString());//该语句和System.out.println(e)一样,打印一个对象,系统会自动调用
//toString()来输出该对象的字符串表现形式。
}
finally //无论是否抛出异常,以及异常是否被catch块捕捉到,都会执行的finally代码块。
{
System.out.println("finally!");
}
System.out.println("over!");//只有没有出现异常,正确执行时和出现异常并异常被catch代码块捕获时,才会
//执行该语句,当出现异常,而catch代码块没有捕捉到异常时,不会执行该语句。
//会在执行完finally语句后,直接向上层调用者跳转,并将异常抛给上层调用者。
}
}
标签:
原文地址:http://www.cnblogs.com/wllbelief-win/p/4354033.html