Java学习 - 异常
Java 异常
Java语言是安全的,根据错误的性质,Java语言将运行错误分为两类: 错误 和 异常
错误(Error)
错误是指程序运行时遇到的硬件的错误,或操作系统,虚拟机等系统软件错误,或操作错误. 错误对于程序而言是致命的,错误将导致程序无法继续运行.
java.lang.Error
是错误类,当产生错误时,Java虚拟机抛出Error类对象. 主要的错误有:
- NoClassDefFoundError : 类定义未找到错误.当没有找到.class文件或运行没有main()方法的
.class
类会抛出. - OutOfMemoryError: 内存溢出. 当用new分配内存且没有可用内存时抛出.
- StackOverflowError : 栈溢出.递归过深抛出.
Java程序本身不能对错误进行处理,只能依靠外界干预.
异常(Exception)
异常是指在硬件,操作系统或虚拟机等系统软件运行正常时,程序产生的运行错误(语义错误). 例如,整数进行除法运算时除数为0,操作数超过数据范围,输入数据格式错误,打开一个文件时发现文件不存在,网络连接中断,数据库连接中断等.
异常对于程序而言是非致命的,异常处理机制能够使程序捕获和处理异常,由异常处理代码调整程序运行方向继续运行.
1. 异常类
java.lang.Exception
异常类是Java语言定义的所有异常类所构成树层次结构的根类,其他异常类是Exception的子类或后代类
Java语言定义的异常类主要分为运行异常和非运行异常.
- RuntimeException 运行异常
- ArithmetException 算数异常
- NullPointerException 空对象异常
- ClassCastException 强制类型转换异常
- NegativeArraySizeException 负数数组长度异常
- ArrayIndexOutOfBoundsException 字符串序号越界异常
- NumberFormatException 数值格式异常
2. 异常处理措施
Java语言的异常处理机制包括异常类体系,异常处理的try语句,抛出自定义异常对象的throw语句,声明方法抛出异常的throws子句和自定义异常类. 这些功能不仅能够捕获并处理异常,还能够主动抛出异常,也能够将异常传递给调用者.
- 创建一个异常类对象的过程称为抛出异常
- 获得异常对象的过程称为捕获异常
- 对异常对象执行操作的过程称为处理异常
3. 异常处理语句
try{
[存在潜在异常的语句]
}catch([异常类] [异常对象]){
[捕获到异常对象并进行处理的语句]
}finally{
[最后必须执行的语句: 无论是否抛出了异常,是否捕获到异常]
}
其中,try
,catch
,finally
是关键字,catch
子句可以有多个,finally
子句可以省略
try-catch-finally将正常执行语句与异常处理语句分离,增强了程序的可读性
- try子句包含可能抛出异常的语句序列.
- catch子句捕获并处理指定类型的异常对象,参数是Exception类及其子类的实例,多个catch子句可以分别处理多种不同类型的异常对象.
- finally 子句包含最后必须执行的语句.
e.g 数值格式异常处理
public class IntArray5{
public static int[] getIns(String[] str){
if(str==null || str.length == 0)
return null;
int[] x = new int[str.length];
int n=0,i=0;
while(i < str.length){
try{
x[n] = Integer.parseInt(str[i]);
++n;
}catch(NumberFormatException ex){
System.out.println("\"" + str[i] + "\"" + ex.toString());
}catch(Exception ex){
ex.printStack();
}finally{
i++;
}
}
if(n==x.length)
return x;
int[] y=new int[n];
System.arraycopy(x,0,y,0,n);
return x;
}
}
4. 抛出异常
4.1 抛出异常对象的throw语句
异常对象可以由Java虚拟机抛出,也可以由程序主动抛出. 如果程序中存在逻辑错误但不是Java的异常,程序也可以采用throw语句主动抛出一个异常对象.throw语句抛出一个异常对象,语法格式如下
throw [异常对象]
e.g 抛出逻辑异常
public void set(int year,int month,int day){
if(month < 1 || month > 12)
throw new Exception("月份错误");
}
4.2 方法声明抛出异常的throws子句
如果一个方法抛出异常,而该方法没有能力处理该异常,则可以在方法声明时,采用throws子句声明该方法将抛出异常. 带有throws子句声明该方法将抛出异常. 带有throws子句的方法声明语法格式如下,其中throws时关键字,"异常类列表"是该方法要抛出的异常类,多个异常类用","分隔. throws子句不是一条独立的语句.
[修饰符] 返回值类型 方法([参数列表]) [throws 异常类列表]
例如,上述set()方法体中抛出异常,如果该方法体内没有处理异常,那么set()方法必须使用throws子句声明抛出异常如下
public void set(int year,int month,int day)throws Exception{
if(month<1 || month > 12)
throw new Exception("月份错误")
}
这么写后,抛出的异常由该方法的调用者处理; 如果调用者也无法处理,那么调用者也需要声明throws子句.
定义异常类
前述set()方法通过throw语句抛出的Exception异常只能够在以下catch子句中被捕获:
catch(Exception ex){
if(ex.getMessage().equals("月份错误"));
}
// ex.getMessage() 返回一个字符串,表示异常信息的类别
而当Java语言提供的异常类不能满足需要时,更好的方法是,应用程序自定义异常类,由catch语句捕获并处理.自定义异常类必须是Exception的子类.
e.g 自定义异常类,日期类的异常处理
public class DateFormatException extends IllegalArgumentException{
public DateFormatException(String message){ super(message); }
public DateFormatException(){ super(); }
}
相应的,set()方法应该修改如下
public void set(int year,int month,int day)throws DateFormatException{
if(year<=-2000 || year > 2500)
throws new DateFormatException(year+",年份不合适,有效年份为-2000~2500.");
if(month < 1 || month > 12)
throws new DateFormatException(month+"月,月份错误");
if(day < 1 || day > MyDate.daysOfMonth(year,month))
throws new DateFormatException(year+"年"+month+"月"+day+"日,日期错误");
this.year=year;
this.month=month;
this.day=day;
}