一、Java7多异常捕获
从Java7开始,一个catch块可以捕获多种类型的异常。
在使用一个catch块捕获多种类型的异常时需要注意:
(1)捕获多种类型的异常时,多种异常类型之间用竖线(|)隔开。
(2)捕获多种类型的异常时,异常变量有隐式的final修饰,因此程序不能对异常变量重新赋值
public class Java7MoreExeptionDemo {
public static void main(String[] args) {
// 数组索引越界 ArrayIndexOutOfBoundsException
// String[] strs = { "1" };
// 数字格式异常 NumberFormatException
// String[] strs = { "1.8","1" };
// 算术异常(除零) ArithmeticException
String[] strs = { "18", "0" };
intDivide(strs);
}
public static void intDivide(String[] strs) {
try {
// try块
int a = Integer.parseInt(strs[0]);
int b = Integer.parseInt(strs[1]);
int c = a / b;
System.out.println("结果是 :" + c);
} catch (ArrayIndexOutOfBoundsException | NumberFormatException
| ArithmeticException e) {
// 将该异常的跟踪栈信息输出到标准错误输出
e.printStackTrace();
try {
e.printStackTrace(new PrintStream(new File(
"E:\\Java课件\\BufferedWriter.txt")));
} catch (FileNotFoundException e2) {
// TODO: handle exception
e2.printStackTrace();
}
} catch (Exception e) {
System.out.println("其他异常");
e.printStackTrace();
}
}
}
二、finally块
finally块一般用来关闭物理资源(数据库连接,网络连接,磁盘文件等),这些物理资 源必须显式关闭。除非在try块、catch块中调用了退出虚拟机的方法
finally创建一个代码块。该代码块在一个 try/catch 块完成之后另一个 try/catch 出现之前执行。finally 块无论有没有异常抛出都会执行。如果异常被抛出,finally 甚至是在没有与该异常相匹配的 catch 子句情况下也将执行。一个方法将从一个 try/catch 块返回到调用程序的任何时候,经过一个未捕获的异常或者是一个明确的返回语句,finally 子句在方法返回之前仍将执行。这在关闭文件句柄和释放任何在方法开始时被分配的其他资源是很有用的。finally 子句是可选项,可以有也可以无。然而每一个 try 语句至少需要一个 catch 或finally 子句
public class FinallyDemo {
public static void main(String[] args) {
RandomAccessFile accessFile = null;
try {
accessFile = new RandomAccessFile("E:\\Java课件\\HelloWorld.java",
"r");
accessFile.writeChars("111");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (accessFile != null) {
System.out.println("----");
try {
accessFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
三、Checked异常和Runtime异常
1、Java的异常被分为两大类:Checked 异常和 Runtime 异常(运行时异常)。
(1)Runtime异常:所有的 RuntimeException 类及其子类的实例;
(2)Checked异常:不是 RuntimeException 类及其子类的异常实例。
2、只有Java语言提供了 Checked 异常,其他语言都没有提供 Checked 异常。Java认为 Checked 异常都是可以被处理(修复)的异常,所以Java程序必须显式处理 Checked 异常。如果程序没有处理 Checked 异常,该程序在编译时就会发生错误,无法通过编译。
3、Checked 异常体现了 Java 的设计哲学:没有完善错误处理的代码根本就不会被执行!
4、Runtime 异常则更加灵活,Runtime 异常无须显式声明抛出,如果程序需要捕获 Runtime 异常,也可以使用 try…catch 块来实现
四、自定义异常类
public class CustomException {
public static void main(String[] args) {
try {
shang(5, 0);
} catch (DivideNegativeException e) {
e.printStackTrace();
} catch (DivideZeroException e) {
e.printStackTrace();
}
}
public static int shang(int x, int y) throws DivideNegativeException,
DivideZeroException {
if (y < 0) {
throw new DivideNegativeException("您输入的除数是" + y + ", 除数不能为负数!"); // 抛出自定义DivideZeroException异常
}
if (y == 0) {
throw new DivideZeroException("您输入的除数是" + y + ", 除数不能为 0!"); // 抛出自定义DivideZeroException异常
}
int m = x / y;
return m;
}
}
/**
* 自定义除0异常
*
* @author sxj
*
*/
class DivideZeroException extends Exception {
private static final long serialVersionUID = 1L;
// 1、提供一个无参构造器
public DivideZeroException() {
}
// 2、带一个字符串参数的构造器
public DivideZeroException(String msg) {
super(msg);
// System.out.println("处理异常");
}
}
/**
* 自定义除负数异常
*
* @author sxj
*
*/
class DivideNegativeException extends Exception {
private static final long serialVersionUID = 1L;
// 1、提供一个无参构造器
public DivideNegativeException() {
}
// 2、带一个字符串参数的构造器
public DivideNegativeException(String msg) {
super(msg);
}
}
五、throws
使用throws声明抛出异常的思路是,当前方法不知道如何处理这种类型的异常,该异常应该由上级调用者处理;如果main方法也不知道如何处理这种类型的异常,也可以使用 throws 声明抛出异常,该异常将交给 JVM 处理。JVM 对异常的处理方法是,打印异常的跟踪栈信息,并中止程序运行
public class ThrowsDemo {
public static void main(String[] args) throws Exception {
// 数组索引越界 ArrayIndexOutOfBoundsException
// String[] strs = { "1" };
// 数字格式异常 NumberFormatException
// String[] strs = { "1.8","1" };
// 算术异常(除零) ArithmeticException
String[] strs = { "18", "0" };
intDivide(strs);
// try {
// intDivide(strs);
// } catch (Exception e) {
// System.out.println("main 处理异常");
// e.printStackTrace();
// }
}
public static void intDivide(String[] strs)
throws ArrayIndexOutOfBoundsException, IndexOutOfBoundsException,
NumberFormatException, ArithmeticException {
int a = Integer.parseInt(strs[0]);
int b = Integer.parseInt(strs[1]);
int c = a / b;
System.out.println("结果是 :" + c);
}
}
六、throw
Java 也允许程序自行抛出异常,自行抛出异常使用 throw 语句来完成如果需要在程序中自行抛出异常,则应使用throw 语句,throw 语句可以单独使用,throw 语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例。
可以通过 throws 关键字在方法上声明该方法要拋出的异常,然后在方法内部通过 throw 拋出异常对象
public class ThrowDemo {
public static void main(String[] args) {
// 数组索引越界 ArrayIndexOutOfBoundsException
String[] strs = { "1" };
// 数字格式异常 NumberFormatException
// String[] strs = { "1.8","1" };
// 算术异常(除零) ArithmeticException
// String[] strs = { "18", "0" };
try {
intDivide(strs);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void intDivide(String[] strs) throws Exception {
try {
// try块
int a = Integer.parseInt(strs[0]);
int b = Integer.parseInt(strs[1]);
int c = a / b;
System.out.println("结果是 :" + c);
} catch (ArrayIndexOutOfBoundsException e) {
throw new Exception("数组索引越界");
} catch (IndexOutOfBoundsException ie) {
throw new Exception("索引越界");
} catch (NumberFormatException ne) {
throw new Exception("数字转换失败");
} catch (ArithmeticException ae) {
throw new Exception("计算错误");
} catch (Exception e) {
System.out.println("其他异常");
e.printStackTrace();
}
}
}
throws、throw区别
(1)throws 用来声明一个方法可能抛出的所有异常信息,throw 则是指拋出的一个具体的异常类型。
(2)通常在一个方法(类)的声明处通过 throws 声明方法(类)可能拋出的异常信息,而在方法(类)内部通过 throw 声明一个具体的异常信息。
(3)throws 通常不用显示地捕获异常,可由系统自动将所有捕获的异常信息抛给上级方法; throw 则需要用户自己捕获相关的异常,而后再对其进行相关包装,最后将包装后的异常信息抛出