Java核心技术 异常
异常概念
程序执行中发生不正常的情况称之为异常,可以将其理解为程序的漏洞,会导致程序崩溃。
异常体系结构
在Java体系中异常用Throwable类表示,其下面又分出两类:Error和Exception。
-
Error指JVM无法解决的问题,如JVM内部崩溃或操作系统出错,这类错误一般不编写特定代码进行处理。
-
Exception指除JVM不可解决的问题外,其他因编程错误或偶然发生的一般性问题引起的不正常情况,这类错误要通过编写针对性代码进行处理。其可以分为两大类:运行期异常和编译器异常(处理异常的理想时期)
(1) RuntimeException类及其子类异常(运行期异常)
运行期异常是不检查异常(JVM不会在编译期检查错误),这些异常一般是由程序逻辑错误引起的,可以选择捕获处理,不处理也可以运行程序。
(2) 除RuntimeException异常外的Exception子类(编译期异常)
从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过,一般情况下不自定义检查异常。

异常处理
try-catch-finally
try块中的程序如果发生异常会转到catch块进行异常匹配,若有多个catch块则会顺序匹配,因此多重catch块的异常类型会从小到大写,无论代码是否出现异常最终都会执行finally块中的代码,因此finally块中一般放释放资源等收尾善后性质的语句。
try
{
// 可能发生异常的程序代码
}catch(ExceptionName e1)
{
//Catch捕获异常处理
}catch(ExceptionName e2){
//Catch捕获异常处理
}finally{
// 无论是否有异常都执行的程序代码
}
Throwable 类主要方法
| 方法名 | 作用 |
|---|---|
| getMessage() | 返回关于发生的异常的详细信息 |
| getCause() | 返回一个Throwable 对象代表异常原因 |
| toString() | 使用getMessage()的结果返回类的串级名字 |
| printStackTrace() | 打印toString()结果和栈层次到System.err,即错误输出流 |
| getStackTrace() | 返回一个包含堆栈层次的数组 |
| fillInStackTrace() | 用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中 |
throw/throws
如果一个方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明,throws 关键字放在方法签名的尾部,可以抛出多个异常,异常之间用逗号隔开。也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。
public class Test
{
//throws用于声明,即告诉JVM我这个代码可能会抛出异常,不一定有异常
public void exceptionDemo(int a) throws Exception
{
//throw是抛出异常,一定有异常,当使用throw抛出异常时,其所在方法必须用throws声明会抛异常,反之则不必须
throw new RemoteException();
}
}
注意事项
- catch 不能独立于 try 存在
- 在 try/catch 后面添加 finally 块并非强制性要求
- try 代码后不能既没 catch 块也没 finally 块
- 当使用try/catch嵌套时有可能发生异常丢失
注意事项4的实例
class VeryImportantException extends Exception{
public VeryImportantException(){
super("Hello");
}
@Override
public String toString() {
return "A very important Exception";
}
}
class HoHumException extends Exception{
public HoHumException(){
super("Hi");
}
@Override
public String toString() {
return "A trivial exception";
}
}
public class LostMessage {
public static void f() throws VeryImportantException {
throw new VeryImportantException();
}
public static void h() throws HoHumException{
throw new HoHumException();
}
public static void main(String[] args) {
try{
//外面catch只接收到了finally中的异常,即内部try的异常被finally异常覆盖
try{
f();
}finally {
h();
}
}catch (Exception e){
System.out.println(e);
}
}
}
自定义异常
在 Java 中你可以自定义异常类,但是要遵循下列规则
- 所有异常都必须是 Throwable 的子类
- 如果希望写检查性异常类,则需要继承 Exception 类
- 如果希望写运行时异常类,则需要继承 RuntimeException 类
实例
自定义异常类
public class MyException extends Exception{
//一定保证在构造方法中调用super(e)父类的构造函数,以便将异常信息插入异常栈中
public MyException(String e){
super(e);
}
}
应用自定义异常类
public class Tran {
static int avg(int n1,int n2)throws MyException{
if (n1<0||n2<0){
//抛出异常并传递错误信息
throw new MyException("年龄不能小于0");
}
if (n1>100||n2>100){
throw new MyException("年龄太大");
}
return (n1+n2)/2;
}
public static void main(String[] args) {
try {
int result=avg(2,109);
System.out.println(result);
}catch (MyException e){
System.out.println(e);
}
}
}
常见异常

编译期异常
代码无法编译,必须进行异常处理才可以运行。
IOException某种I / O异常

ClassNotFoundException找不到类异常

运行期异常
代码可以正常编译,但运行时会报的异常
NullPointerException空指针异常
public class Test {
public static void main(String[] args) {
//指向空的数据会报NullPointerException
int[] a = null;
System.out.println(a[0]);
}
}
IndexOutOfBoundsException下标越界异常
public class Test {
public static void main(String[] args) {
//数组下标越界,因为数组从0起到长度-1,报ArrayIndexOutOfBoundsException
int[] a = new int[3];
System.out.println(a[3]);
}
}
public class Test {
public static void main(String[] args) {
//字符串下标越界,因为字符串底层也是由一个byte数组实现,报StringIndexOutOfBoundsException
String s="abc";
System.out.println(s.charAt(3));
}
}
ClassCastException类型转换异常
public class Test {
public static void main(String[] args) {
//ClassCastException异常,一般多见于强转中
Object d=new String();
Date date=(Date)d;
}
}
NumberFormatException转换数字格式异常
public class Test {
public static void main(String[] args) {
//NumberFormatException,因为字符串中存放的不是数字,所以无法直接转
String s="abc";
int n=Integer.parseInt(s);
}
}
InputMismatchException输入不匹配异常
public class Test {
public static void main(String[] args) {
//因为输入的数据和接收变量的类型不同引发InputMismatchException异常
Scanner scanner=new Scanner(System.in);
int n= scanner.nextInt();
System.out.println(n);
}
}
ArithmeticException算数异常
public class Test {
public static void main(String[] args) {
//因为除数为0,不符合数学规则,触发ArithmeticException算数异常
System.out.println(9/0);
}
}
总结
异常对于Java程序是非常重要的,可以保证代码健壮性、安全性等,但如果没有完美解决异常的方案,请不要盲目处理,将其抛出即可,一般开发中还是尽量避免不必要的异常。
- Author
- 小葳宝贝最爱吃饭

浙公网安备 33010602011771号