Java 第七章 异常处理
一、异常概述与异常体系结构
概述
二、常见异常
java.lang.Throwable的子类
java.lang.Error:一般不编写针对性的代码进行处理
java.lang.Exception:可以进行异常的处理
编译时异常(checked/Runtime):
IOExcption、FileNotFoundException
代码示例
public static void test9()
{
File file = new File("hello.txt");
FileInputStream fis = new FileInputStream(file);
//文件找不到异常::FileNotFoundException
int data = fis.read();//编译异常:IOException
while(data!=-1)
{
System.out.println(data);
data = fis.read();//编译异常:IOException
}
fis.close();//防止内存泄漏
}
运行时异常(unchecked):
NullPointerException、IndexOutOfBoundsException、ClassCastException、NumberFormatException、InputMismatchException、ArithmeticException
代码示例
public static void test1()
{
int[] a = null;
System.out.println(a[0]);//空指针异常:NullPointerException
}
public static void test2()
{
int[] a = new int[5];
System.out.println(a[5]);//数组访问越界异常:ArrayIndexOutOfBoundsException
}
public static void test3()
{
String str = "abc";
System.out.println(str.charAt(3));
//字符串角标越界异常:StringIndexOutOfBoundsException
}
public static void test5()
{
Object o = new Date();
String s = (String) o;//转换时异常:ClassCastException
}
public static void test6()
{
String s = "a23";
int num = Integer.parseInt(s);//格式异常:NumberFormatException
System.out.println(num);
}
public static void test7()
{
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();//输入异常:InputMismatchException
sc.close();
System.out.println(num);
}
public static void test8()
{
System.out.println(2/0);//算数异常:ArithmeticException
}
面试题:常见的异常都有哪些?举例说明
三、异常处理机制
在编写程序时,经常要在可能出现错误的地方加上检测的代码,过多的if-else分支会导致程序的代码加长、臃肿,可读性差,因此采用异常处理机制。
Java异常处理:Java采用的异常处理机制,是将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序简洁、优雅,并易于维护
过程一:“抛”:程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象,并将此对象抛出。一旦抛出对象,其后代码不再执行
过程二:“抓”:可以理解为异常的处理方式:①try-catch-finally ②throws
异常处理方式一:try-catch-finally
代码格式
try
{
//可能出现异常的代码
}catch(异常类型1 变量名1)
{
//处理异常的方式1
}catch(异常类型2 变量名2)
{
//处理异常的方式2
}catch(异常类型3 变量名3){
//处理异常的方式3
}
}
.....
finally
{
//一定会执行的代码
}
代码示例
public static int test9()
{
FileInputStream fis = null;
try {
File file = new File("Input.txt");
fis = new FileInputStream(file);
int data = fis.read();
while (data != -1) {
System.out.println(data);
data = fis.read();
}
return 0;
} catch (FileNotFoundException exception) {
System.out.println("找不到文件!");
exception.printStackTrace();
} catch (IOException ioException) {
System.out.println("出现编译错误!");
ioException.printStackTrace();
}finally {
try {
fis.close();
}catch (IOException exception)
{
System.out.println("出现编译错误!");
exception.printStackTrace();
}catch (NullPointerException exception)
{
System.out.println("出现空指针错误!");
exception.printStackTrace();
}
}
return 1;
}
说明
1.finally是可选的
2.使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配
3.一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成,就跳出当前的try-catch结构(无finally),继续执行其后的代码
4.catch中的异常类型如果没有子父类关系,则声明顺序无所谓;如果存在子父类关系,则要求子类一定声明在父类的上面。否则,报错。
5.常用的异常对象处理方式:①String getMessage() ②printStackTrace()
6.在try结构中声明的变量,再出了try结构以后,就不能再被调用
7.try-catch-finally结构可以嵌套
体会1:使用try-catch-finally处理编译时异常,使得程序在编译时就不再报错,但是运行时仍可能报错,相当于将编译时可能出现的异常,延迟到运行时出现
体会2:开发中,由于运行时异常比较常见,所以我们通常不针对运行时异常编写try-catch-finally。针对于编译时异常,我们一定要考虑异常的处理
finally的有关使用
1.finally是可选的
2.finally中声明的是一定会被执行的代码,即使catch中又出现异常,try中有return语句,catch中有return语句
3.像数据库连接、输入输出流、网络编程socket等资源,JVM是不能自动回收的,需要我们手动释放资源。此时的资源释放,需要声明在finally当中
异常处理方式二:throws + 异常类型
1.“throw + 异常类型”写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。
一旦此方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出。异常代码后续的代码,不再执行!
2.体会:
try-catch-finally:真正的将异常给处理掉
throws的方式只是将异常抛给了方法的调用者,并没有真正的处理掉异常
开发中如何选择使用try-catch-finally 还是throws?
①如果父类被重写的方法没有throws方法处理异常,则子类重写的方法也不能用throws,意味着如果子类重写的方法中有异常,必须用try-catch-finally方式处理。
②执行的方法A中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。建议这几个方法用throws的方式进行处理,而执行的方法A可以考虑用try-catch-finally方式进行处理
重写方法异常抛出的原则
1.子类重写的方法抛出的异常不大于父类被重写的方法抛出的异常类型
四、手动抛出异常:throw
开发中可以通过throw +new 异常类型 来手动抛出异常
@Override
public int compareTo(Object o)
{
if(o == this) return 0;
else if(o instanceof ComparableCircle)
{
ComparableCircle o1 = (ComparableCircle) o;
if(this.getRadius() > o1.getRadius()) return 1;
else if(this.getRadius() == o1.getRadius()) return 0;
else return -1;
}
else throw new RuntimeException("错误:类型不匹配!");
}
五、用户自定义异常类
如何自定义异常类?
1.继承于现有的异常结构:RuntimeException、Exception
2.提供全局常量:serialVersionUID
3.提供重载构造器
代码示例
public class DismatchExcption extends RuntimeException
{
public static final long serialVersionUID = 123;//序列号
public DismatchExcption()
{
}
public DismatchExcption(String msg)
{
super(msg);
}
}