异常是导致程序中断执行的一种指令流,一旦产生异常没有正常处理的话,那么程序江湖中断执行。
范例:观察产生异常的代码
public class Hello{
public static void main(String args[]){
System.out.println("AAAAAA 计算开始 AAAAAA");
System.out.println("BBBBBB 除法计算:"+(10/0)+" BBBBBB");
System.out.println("CCCCCC 计算结束 CCCCCC");
}
}
如果要在Java中进行异常的处理可以使用三个关键字的组合完成:try、catch、finally。有如下语法:
而此时给出的语法也有三种组合模式:try…catch、try…catch…finally、try…finally。
范例:实现异常的处理操作
public class Hello{
public static void main(String args[]){
System.out.println("AAAAAA 计算开始 AAAAAA");
try{
System.out.println("BBBBBB 除法计算:"+(10/0)+" BBBBBB");
}catch(ArithmeticException e){//e是一个对象
System.out.println(e);
}
System.out.println("CCCCCC 计算结束 CCCCCC");
}
}
此时程序出现异常仍可以正常执行完毕。
要想完整的输出异常信息,则可以使用printStackTrace()方法完成。
public class Hello{
public static void main(String args[]){
System.out.println("AAAAAA 计算开始 AAAAAA");
try{
System.out.println("BBBBBB 除法计算:"+(10/0)+" BBBBBB");
}catch(ArithmeticException e){//e是一个对象
e.printStackTrace();
}
System.out.println("CCCCCC 计算结束 CCCCCC");
}
}
public class Hello{
public static void main(String args[]){
System.out.println("AAAAAA 计算开始 AAAAAA");
try{
System.out.println("BBBBBB 除法计算:"+(10/0)+" BBBBBB");
}catch(ArithmeticException e){//e是一个对象
e.printStackTrace();
}finally{
System.out.println("*************************");
}
System.out.println("CCCCCC 计算结束 CCCCCC");
}
}
异常产生之后找到了相应的catch语句执行,而后处理异常完毕后继续执行finally的代码。
public class Hello{
public static void main(String args[]){
System.out.println("AAAAAA 计算开始 AAAAAA");
try{
System.out.println("BBBBBB 除法计算:"+(10/2)+" BBBBBB");
}catch(ArithmeticException e){//e是一个对象
e.printStackTrace();
}finally{
System.out.println("*************************");
}
System.out.println("CCCCCC 计算结束 CCCCCC");
}
}
在一个try语句之后可以编写多个catch进行处理,模拟一个输入的数字计算操作,假设要计算的数字使用过初始化参数设置的。
范例:修改程序代码
public class Hello{
public static void main(String args[]){
System.out.println("AAAAAA 计算开始 AAAAAA");
try{
int x = Integer.parseInt(args[0]);
int y = Integer.parseInt(args[1]);
int result=x/y;
System.out.println("BBBBBB 除法计算:"+result+" BBBBBB");
}catch(ArithmeticException e){//e是一个对象
e.printStackTrace();
}finally{
System.out.println("*************************");
}
System.out.println("CCCCCC 计算结束 CCCCCC");
}
}
下面就有了这样几种执行情况:
public class Hello{
public static void main(String args[]){
System.out.println("AAAAAA 计算开始 AAAAAA");
try{
int x = Integer.parseInt(args[0]);
int y = Integer.parseInt(args[1]);
int result=x/y;
System.out.println("BBBBBB 除法计算:"+result+" BBBBBB");
}catch(ArithmeticException e){//e是一个对象
e.printStackTrace();
}catch(NumberFormatException e){//e是一个对象
e.printStackTrace();
}catch(ArrayIndexOutOfBoundsException e){//e是一个对象
e.printStackTrace();
}finally{
System.out.println("*************************");
}
System.out.println("CCCCCC 计算结束 CCCCCC");
}
}
两个异常类的继承结构
java.lang.ArithmeticException | java.lang.NumberFormatException |
---|---|
可以发现所有的异常类都是java.lang.Throwable的子类,此类定义如下:
public class Throwable extends Object implements Serializable
可以发现Throwable直接是Object子类。从JDK1.0开始提供。但是在Throwable下有两个子类,因此在开发中几乎不会考虑Throwable处理。
面试题:请解释Throwable下的Error和Exception子类的区别。
public class Hello{
public static void main(String args[]){
System.out.println("AAAAAA 计算开始 AAAAAA");
try{
int x = Integer.parseInt(args[0]);
int y = Integer.parseInt(args[1]);
int result=x/y;
System.out.println("BBBBBB 除法计算:"+result+" BBBBBB");
}catch(Exception e){//e是一个对象
e.printStackTrace();
}finally{
System.out.println("*************************");
}
System.out.println("CCCCCC 计算结束 CCCCCC");
}
}
在实际开发中如果有明确要求,就分开处理。其他情况采用Exception是最方便的。
用户如何知道那些代码会产生怎样的异常?Java中提供throws关键字,其主要目的是明确告诉用户执行某一个方法有可能会产生哪些异常。所以throws主要是用于方法的声明处。
范例:观察throws关键字的使用
class MyMath{
public static int div(int x,int y)throws Exception{
return x/y;
}
}
表示如果想执行本语句就必须进行异常处理。
范例:不处理异常直接调用
class MyMath{
public static int div(int x,int y)throws Exception{
return x/y;
}
}
public class Hello{
public static void main(String args[]){
System.out.println(MyMath.div(10, 2));
}
}
代码中出现throws声明,表示必须强制性进行异常处理操作。
范例:正常调用形式
class MyMath{
public static int div(int x,int y)throws Exception{
return x/y;
}
}
public class Hello{
public static void main(String args[]){
try{
System.out.println(MyMath.div(10, 2));
}catch(Exception e) {
e.printStackTrace();
}
}
}
但是使用了throws之后还有一个传递的问题,主方法也是一个方法,所以主方法也可以使用throws,那么就表示此时的主方法不进行异常的处理,而交给被调用处处理。
class MyMath{
public static int div(int x,int y)throws Exception{
return x/y;
}
}
public class Hello{
public static void main(String args[]) throws Exception{
System.out.println(MyMath.div(10, 0));
}
}
主方法之上就由JVM进行默认处理,一般主方法中应该把异常处理完成。
所有异常对象都是Java负责实例化,我们只能对异常进行捕获。Java中允许用户自己实例化异常对象,要抛出这个异常,就必须使用throw关键字。
范例:自己手工抛出异常
public class Hello{
public static void main(String args[]) {//throws Exception
throw new Exception("这是一个异常。");
}
}
public class Hello{
public static void main(String args[]) {//throws Exception
try{
throw new Exception("这是一个异常。");
}catch(Exception e) {
e.printStackTrace();
}
}
}
class MyMath{
public static int div(int x,int y)throws Exception{//交给被调用处处理
int result=0;//保存计算结果
System.out.println("************begin*************");
result = x/y;
System.out.println("*************end*************");
return result;
}
}
public class Hello{
public static void main(String args[]) {//throws Exception
try{
System.out.println(MyMath.div(10, 2));
}catch(Exception e) {
e.printStackTrace();
}
}
}
一旦程序出现错误,这个时候的运行结果如下。
范例:加入异常控制
class MyMath{
public static int div(int x,int y)throws Exception{//交给被调用处处理
int result=0;//保存计算结果
System.out.println("************begin*************");
try{
result = x/y;
}catch(Exception e){
throw e;//继续向上抛
}finally{
System.out.println("*************end*************");
}
return result;
}
}
public class Hello{
public static void main(String args[]) {//throws Exception
try{
System.out.println(MyMath.div(10, 0));
}catch(Exception e) {
e.printStackTrace();
}
}
}
在以后的开发之中,一定会牵扯到资源的使用,例如文件、数据库操作前一定要打开,操作后一定要关闭。但是以上给出的异常处理模型可以简化:try…finally。
class MyMath{
public static int div(int x,int y)throws Exception{//交给被调用处处理
int result=0;//保存计算结果
System.out.println("************begin*************");
try{
result = x/y;
}finally{
System.out.println("*************end*************");
}
return result;
}
}
public class Hello{
public static void main(String args[]) {//throws Exception
try{
System.out.println(MyMath.div(10, 0));
}catch(Exception e) {
e.printStackTrace();
}
}
}
看段代码:
public class Hello{
public static void main(String args[]) {
int num = Integer.parseInt("123");
System.out.println(num*num);
}
}
方法中出现throws就要进行异常处理,但此时并没有,观察NumberFormat类的继承结构。
因为NumberFormat类属于RuntimeException的子类,所以该异常属于选择性处理,即使不处理,编译的时候也不会出错,但是运行的时候会出错。
面试题:请解释Exception与RuntimeException的区别?列举出几个常见的RuntimeException。
断言指的是在程序编写的过程之中,确定代码执行到某行之后数据一定是某个期待的内容。
范例:观察断言
断言默认情况不会启用,只有在程序运行时增加了配置参数才可以使用。
java -ea Hello
Java异常类之中提供了大量类型,但是这些类型之中几乎都是与语法有关的异常,缺少业务有关类型,例如:输入某人成绩,如果超过100,那么就应该产生对应的异常,这些往往需要开发者自己定义,正因为如此才需要自定义异常类的概念。
异常类型主要有两个:Exception、RuntimeException。
范例:设计一个成绩异常