## Java编程那些事儿82——异常处理语法1
陈跃峰
出自:[http://blog.csdn.net/mailbomb](http://blog.csdn.net/mailbomb)
### 10.3 异常处理语法
为了方便程序员进行异常的处理,在Java语言中创建了一套语法,这些语法主要分为以下几个部分:
1、抛出异常
当程序运行时,如果发现异常的情况,通过生成对应的异常对象,并将该异常对象传递给Java的运行时系统,使得系统中包含该异常信息,这样的过程被称作抛出异常。
抛出异常是整个异常处理机制的起点,也是异常的发源地,一般出现在项目底层的代码中。
2、声明异常
当一个方法在执行时,除了能够完成正常的功能以外,还可以出现一些异常情况,为了提醒调用该方法的程序员注意处理这些异常情况,需要在方法的声明中将这些异常声明出来,这就是声明异常。
声明异常的语法使得异常处理更加容易进行实现。
3、捕获异常及异常处理
当异常被抛出以后,如果不进行处理,则异常会在方法调用过程中一直进行传递,直到最后一个方法,在J2SE中也就是main方法,最终将显示在控制台。
在实际项目中,当异常被抛出以后,需要首先捕获到该异常,按照异常的种类不同,分别进行处理。
4、声明自定义异常类
虽然在JDK API中提供了几百个异常类,但是这些异常所代表的还只是常见的异常情况,在实际使用时还是无法代表所有的异常情况,所以Java语言运行声明自定义的异常类,使用这些自定义的异常类来代表实际项目中JDK API无法代表的异常情况。
下面依次详细介绍一下这些语法的相关规则。
### 10.3.1 抛出异常
在书写项目中相关的底层基础代码时,相关的方法除了实现应该实现的功能以外,还需要考虑到各种异常情况,如果出现该代码所在的方法无法处理的异常情况时,则应该在该方法内部抛出对应类型的异常时,使得整个方法的逻辑比较严谨。
例如,下面是一个实现将十进制数字转换为二进制或8进制字符串的方法:
~~~
/**
* 将自然数转换为二进制或八进制字符串
* @param value 需要转换的自然数
* @param radix 基数,只能取2或8
* @return 转换后的字符串
*/
public static String toString(int value,int radix){
if(value == 0){
return "0";
}
StringBuffer s = new StringBuffer();
int temp; //余数
while(value != 0){ //未转换结束
temp = value % radix; //取余数
s.insert(0,temp); //添加到字符串缓冲区
value /= radix; //去掉余数
}
return s.toString();
}
~~~
在该方法中使用除n取余的方法,将参数value转换为对应的字符串,当在main方法中以书写如下代码时:
System.out.println(toString(12,2));
则程序的运行结果是:
1100
这样在正常的情况下,程序获得了正确的结果,但是该方法由于逻辑的限制,只能实现将“自然数”转换为“二进制或八进制”字符串,如果在其它程序员误传入非法的参数时,则程序会获得不正常的结果,例如书写如下调用的代码时:
System.out.println(toString(12,16));
则程序的运行结果是:
12
这个结果在转换的逻辑上就是错误的。这样就因为其它程序员误传入非法参数而出现了错误的结果。如果该方法作为实际项目的一个逻辑存在,则会由于该方法的问题导致后续其它的功能也发生错误,这是每个程序员都不希望看到的。
所以该方法虽然在功能上达到了要求,但是逻辑还是不严谨的,还需要在其它程序员调用该方法时传入非法参数这样的异常情况时,将这种异常报告出来,这就需要抛出异常的的代码了。
抛出异常的语法格式为:
throw 异常对象;
例如:
throw new NullPointerException();
或
IllegalArgumentException e = new IllegalArgumentException();
throw e;
该代码书写在方法或构造方法的内部。该语法中,使用throw关键字,后续为代表对应异常情况的异常类类型的对象。当系统执行到该代码时,将中止当前方法的执行,而直接返回到调用该方法的位置。所以在该代码下面不能直接书写其它的代码,因为这些代码将永远无法执行到。例如:
throw new NullPointerException();
int n = 10; //语法错误,该代码无法到达
按照该语法,则上面的转换方法改造以后的代码如下:
~~~
/**
* 将自然数转换为二进制或八进制字符串
* @param value 需要转换的自然数
* @param radix 基数,只能取2或8
* @return 转换后的字符串
*/
public static String toString(int value,int radix){
//判断异常的代码
if(value <0){
throw new IllegalArgumentException("需要转换的数字不是自然数!");
}
if(radix != 2 && radix != 8){
throw new IllegalArgumentException("进制参数非法");
}
if(value == 0){
return "0";
}
StringBuffer s = new StringBuffer();
int temp; //余数
while(value != 0){ //未转换结束
temp = value % radix; //取余数
s.insert(0,temp); //添加到字符串缓冲区
value /= radix; //去掉余数
}
return s.toString();
}
~~~
这里,当value的值小于0时,则抛出非法参数异常,当radix的值不是2或8时,则抛出非法参数异常。
这样在执行如下代码:
~~~
System.out.println(toString(12,2));
System.out.println(toString(12,16));
~~~
则程序的执行结果是:
1100
Exception in thread "main" java.lang.IllegalArgumentException: 进制参数非法
at ThrowException.toString(ThrowException.java:22)
at ThrowException.main(ThrowException.java:7)
这里当参数符合要求时,则输出正确结果1100,如果参数不合法,则抛出异常,由于异常没有得到处理,则将终止程序的执行,则控制台输出异常的信息,并显示异常的类型以及异常出现的位置。
这样,就通过抛出异常的语法,使得该方法的逻辑比较严谨,在方法的参数不合法,即出现异常情况时,将这个异常报告出来,使得该方法不会出现错误的结果。
另外,抛出的异常将传递给运行时系统,这样就将这种异常的情况传递出来,提醒其它的结构进行处理。
### 10.3.2 声明异常
异常虽然被抛出了,但是由于抛出异常的代码是在方法或构造方法的内部的,在调用方法或构造方法时一般是无法看到方法或构造方法的源代码的,这样调用的程序员就无法知道该方法或构造方法将出现怎样的异常情况,所以需要有一种语法,可以使得调用的程序员可以看到被调用的结构可能出现的异常情况,这就是声明异常的语法。
声明异常的语法类似于药品上的副作用说明,在患者服用药品时,知道药品的正常功能,但是无法详细了解药品的成分以及每种成分的含量(类似于源代码),但是在药品的说明上都有副作用的说明,例如过敏者不能服用等,这些和声明异常的语法在功能上是类似。
声明异常的语法格式为:
throws 异常类名
例如:
public static void test(int n) throws IllegalArgumentException,IOException
public Test()throws IllegalArgumentException
该语法使用在方法和构造方法的声明以后,在throws关键字以后,书写该方法或构造方法可能出现的异常,在这里需要书写异常类的类名,如果有多个,则使用逗号分隔这些异常类名即可。
这里需要注意的是:
1、这些异常必须是该方法内部可能抛出的异常
2、异常类名之间没有顺序
3、属于RuntimeException子类的异常可以不书写在throws语句以后,但是另外一类异常如果可能抛出则必须声明在throws语句之后
通过在对应的方法或构造方法声明中书写throws语句,使得调用该方法或构造方法的程序员可以在调用时看到对应结构可能出现的异常情况,从而提示对于这些异常情况进行处理,从而增强程序的健壮性。
而且即使在程序由于未处理对应的异常而导致程序在运行时出现错误时,也可以使程序员可以通过对应的提示获得错误的原因,并指导程序员进行逻辑的修正,这样都可以提高程序编写时的效率,也可以使程序员更加容易的编写出逻辑严谨的代码,从而增加项目的质量,提高程序的稳定性。
但是声明异常以后,异常还是存在的,异常还没有获得处理,在异常体系中最重要的还是捕获到异常,然后针对异常的类型不同作出对应的处理。
- 前言
- (1)序言
- (2)程序设计是什么?
- (3)你适合学习程序设计吗?
- (4)如何学好程序设计?
- (5)程序设计介绍小结
- (6)计算机软件基本概念
- (7)进制的概念
- (8)计算机内部的数据表达
- (9)网络编程基础
- (10)Java语言简介
- (11)JDK的获得、安装和配置
- (12)第一个HelloWorld程序
- (13)Eclipse基本使用
- (14)Eclipse基础使用进阶
- (15)如何学好Java语法
- (16)代码框架、关键字和标识符
- (17)基本数据类型
- (18)变量和常量
- (19)数据类型转换
- (20)空白、语句结束和注释
- (21)算术运算符
- (22)比较运算符
- (23)逻辑运算符
- (24)赋值运算符
- (25)位运算符
- (26)移位运算符
- (27)其它运算符
- (28)运算符优先级
- (29)表达式
- (30)流程控制基础
- (31)if语句语法(1)
- (32)if语句语法(2)
- (33)if语句语法(3)
- (34)switch语句语法
- (35)while语句语法
- (36)do-while语句语法
- (37)for语句语法
- (38)break和continue语句
- (39)流程控制综合示例1
- (40)流程控制综合示例2
- (41)流程控制综合示例3
- (42)流程控制综合练习
- (43)数组概述
- (44)数组基础语法
- (45)数组使用示例1
- (46)数组使用示例2
- (47)数组使用示例3
- (48)多维数组基础
- (49)多维数组使用示例1
- (50)多维数组使用示例2
- (51)多维数组练习
- (52)方法声明
- (53)方法声明示例
- (54)方法调用
- (55)方法重载和参数传递
- (56)方法练习
- (57)面向对象基础
- (58)类(一)
- (59)类(二)
- (60)对象
- (61)面向对象设计方法和面向对象特性(一)
- (62)继承(二)
- (63)多态性
- (64)访问控制符、修饰符和其它关键字
- (65)static修饰符
- (66)final修饰符
- (67)this和super
- (68)抽象类和接口(一)
- (69)抽象类和接口(二)
- (70)抽象类和接口(三)
- (71)内部类简介
- (72)包的概念
- (73)JDK文档使用
- (74)java.lang包介绍1
- (75)String类使用
- (76)StringBuffer类和System类
- (77)包装类
- (78)时间和日期处理
- (79)Random随机处理
- (80)集合框架简述
- (81)异常处理概述
- (82)异常处理语法1
- (83)异常处理语法2
- (84)IO简介
- (85)IO类体系
- (86)文件操作之File类使用
- (87)文件操作之读取文件
- (88)文件操作之写文件
- (89)读取控制台输入
- (90)装饰流使用1
- (91)装饰流使用2
- (92)IO使用注意问题
- (93)多线程基础
- (94)多线程实现方式1
- (95)多线程实现方式2
- (96)多线程使用示例1
- (97)多线程使用示例2
- (98)多线程问题及处理1
- (99)多线程问题及处理2
- (100)多线程问题及处理3
- (101)网络编程概述
- (102)网络编程技术1
- (103)网络编程技术2
- (104)网络编程技术3
- (105)网络编程技术4
- (106)网络编程技术5
- (107)网络协议概念
- (108)网络编程示例1
- (109)网络编程示例2
- (110)网络编程小结