1、异常分类
在程序运行过程中可能发生的错误叫异常。
Object类的直接子类Throwable是系统级异常,无法使用java程序进行处理。
Exception是程序级异常,其有一RuntimeException为代表的非检查异常(unchecked Exception),以IOException为代表的检查性异常(checked Exception)。
RuntimeException运行时异常是只能在程序运行时才能发现的异常;大部分可通过逻辑判断避免,逻辑严谨的程序可以避免发生。
checked Exception检查异常,程序在编译阶段,有java编译器发现,并需要编码处理。
2、Java常见异常
1.空指针异常:java.lang.NullPointerException
空指针异常时一个运行时异常,引用一个没有初始化的null对象的属性或方法时,会发出空指针异常。发出空指针异常时,需要检查对象是否使用new关键字进行初始化。
2. 类型强转异常:java.lang.ClassCastException
当被一个对象赋值给另外一个类型的引用时,需要进行类型强制转换;当对象与引用类型不存在父子关系,且没有进行先向上转型,再进行向下转型,则会抛出该异常。类型强制转换的本质就是类型还原,如果不是类型还原就会抛出强制转换异常。
3. 算数运算异常:java.lang.ArithmeticException
4. 数字格式化异常:java.lang.NumberFormatException
5. 传递非法参数异常:IllegalArgumentException
6. 向数组中存放与声明类型不兼容对象异常:ArrayStoreException
7. 下标越界异常:IndexOutOfBoundsException
8. 创建一个大小为负数的数组错误异常:NegativeArraySizeException
9. 数字格式异常:numberFormatException
10. 安全异常:SecurityException
11. 不支持的操作异常:UnsupportedOperationException
3 、异常处理
捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
a) 捕获异常
关键字:try catch finally
try:可以将有可能发生异常的代码使用try括起来。
catch:用来捕获try抛出的异常代码块,没有try块,catch块不能单独存在。一个代码块中,可能发生多个异常,可以使用多个catch捕获异常,父类异常要写在后面。使用一个catch同时捕获多个异常时,异常不能有父子关系。
如果一个程序段中有多个catch,则程序在找到合适的异常类型后就不再执行后面的catch。
finally:finally语句放在try …catch语句后,用于执行不管是否异常都要运行的代码。在try或catch中,如果执行return语句,finally块仍然执行。但如果执行了System.exit(0),将直接退出程序,不执行finally。
有try块放到了事务代码中,catch异常后,如果需要回滚事务,一定要注意手动回滚事务。
finally块必须对资源对象、流对象进行关闭,有异常也要做try-catch。不能在finally块中使用return,finally块中的return返回后方法结束执行,不会再执行try块中的return语句。
一旦在finally块中使用了return或throw语句,将会导致try块,catch块中的return,throw语句失效。
例1:编写一段代码,读取某个Java程序,并把读取的代码显示到控制台
public class TestCheckException {
public static void main(String[] args) {
File file = new File("D:\\javaworkspace\\classroom\\src\\classroom\\chap7\\inter\\Animal.java");
if(file.exists()){
BufferedReader bufferedReader = null;
InputStreamReader reader = null;
FileInputStream inputStream = null;
try{
inputStream = new FileInputStream(file);
reader = new InputStreamReader(inputStream);
bufferedReader = new BufferedReader(reader);
String line = bufferedReader.readLine();
while(line!=null){
System.out.println(line);
line = bufferedReader.readLine();
}
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
if(inputStream!=null){
try{
inputStream.close();
}catch(IOException e){
}
}
}
}
System.out.println("main方法执行完毕");
}
}
b) 声明异常
当方法内部可能发生异常时,且没有编写异常捕获代码,则可以对方法进行异常声明。异常声明一般在方法定义时进行声明,异常声明的目的是把异常告诉或传递到方法的调用者。
throw:用在方法体内,表示抛出异常,由方法体内的语句处理。不能单独使用,要么和try…catch…一起使用,要么和throws一起使用。
throws: 用在参数列表的后面,throws关键字后面,可以跟多个异常,中间用逗号分开,且不受父子关系的影响。其抛出的异常,由调用该函数的函数处理。
例2:
public void showInfo2() throws RuntimeException,IllegalArgumentException{
if(computer<0){
throw new RuntimeException("课程成绩不能为负2");
}
if(computer>100){
throw new IllegalArgumentException("成绩无效");
}
System.out.println("姓名:"+name+",成绩:"+computer);
}
4、练习
1、 编写应用程序,从命令行传入两个整型数作为除数和被除数。要求程序中捕获NumberFormatException 异常和ArithmeticException异常,而且无论在哪种情况下,“总是被执行”这句话都会在控制台输出。
1.1 在命令行输入 java A
1.2 在命令行输入 java A 1 2
1.3 在命令行输入 java A 1 3a
1.4 在命令行输入 java A 1 0
public class Subject1 {
public static void main(String[] args) {
//Scanner不能输入空字符串
String str;
BufferedReader a = new BufferedReader(new InputStreamReader(System.in));
try {
str = a.readLine();
//str = new Scanner(System.in).next();
String[] arr = str.split(" ");
String strx = arr[2];
String stry = arr[3];
int x = Integer.parseInt(strx);
int y = Integer.parseInt(stry);
System.out.println(x/y);
}
catch(IOException e){
e.printStackTrace();
}
catch (NumberFormatException e) {
e.printStackTrace();
}finally{
System.out.println("总是被执行");
}
}
}
2、 编写一个方法,比较两个字符串。假如其中一个字符串为空,会产生NullPointerException异常,在方法声明中通告该异常,并在适当时候触发异常,然后编写一个程序捕获该异常。
public class Subject2 {
public void stringWay(String str,String str1){
if(str==null || str1==null){
try {
throw new NullPointerException();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Subject2 s = new Subject2();
String str = null;
String str1 = "nini";
s.stringWay(str, str1);
}
}
3、 编写一个检查给定的数字的数据类型是否为byte的程序,如果此数字超出byte数据类型表示的数的范围,则引发用户自定义的异常ByteSizeException,并显示相应的错误信息
public class Test {
public static void main(String[] args) throws ByteSizeException {
try {
byte b = new Scanner(System.in).nextByte();
} catch (Exception e) {
throw new ByteSizeException("输入的数字不是byte类型");
}
}
}