1 异常是什么
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。
比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error;
如果你用System.out.println(11/0),那么你是因为你用0做了除数,会抛出 java.lang.ArithmeticException 的异常。
2 为什么要引入异常处理机制
public class TestException {
public static void main(String[] args) throws Exception {
String s = null;
System.out.println(s.equals(null));
System.out.println("【END】程序执行完毕!");
}
}
程序执行结果:
Exception in thread "main" java.lang.NullPointerException
at org.example.exceptionHandling.TestException.main(TestException.java:7)
以上的程序由于产生了空指针异常,所以最终的程序也没有能够输出最后的提示信息,所以只要出现了异常,这个时候就会发现程序都无法正常的执行完毕,所以为了可以让程序在出现异常之后可以继续正确的执行完毕,那么最佳的做法就是要引入异常的处理机制,保护程序的正确执行。
3 异常处理
在程序中为了保证出现了异常之后可以正确的执行完毕,就需要进行合理的异常处理,而对于异常处理主要是通过: try、catch、finally三个关键字来决定的,下面是异常的处理语法结构:。
try {
// 有可能产生异常的程序代码
} [ catch (异常类型异常对象) {
// 异常的处理
} catch (异常类型异常对象) {
// 异常的处理
} ... ] [ finally {
// 最终一定会执行的程序代码
} ]
对于以上所给出的异常处理结构可以使用如下的几种组合方式: try ..catch、try ...catch .finally、try...finally。
public class TestException {
public static void main(String[] args) throws Exception {
try { // 将有可能产生异常的语句直接放在 try 中
int result = 10 / 0; // 产生异常之后,之后的代码将不再继续执行
System.out.println("【计算结果】" + result);
}catch (ArithmeticException e){ // 表示异常出现了错误之后的处理
// 在进行异常处理的时候如果直接输出异常对象,那么所获得的异常信息是不完整的
e.printStackTrace(); // 输出异常信息
}
System.out.println("【计算结束】----------");
}
}
程序执行结果:
java.lang.ArithmeticException: / by zero
at org.example.exceptionHandling.TestException.main(TestException.java:11)
【计算结束】----------
由于此时存在有异常的处理,所以即便程序中出现了异常,那么也会正常的执行完整个的程序代码,所以引入异常处理的最大优势就在于可以保证程序的顺序执行完毕,需要注意的是,在异常处理中除了try...catch组合之外,也可以使用try...eatch...finally的组合进行操作,而finally表示不管是否出现异常都会执行的处理语句。
public class TestException {
public static void main(String[] args) throws Exception {
try { // 将有可能产生异常的语句直接放在 try 中
int result = 10 / 0; // 产生异常之后,之后的代码将不再继续执行
System.out.println("【计算结果】" + result);
} catch (ArithmeticException e){ // 表示异常出现了错误之后的处理
// 在进行异常处理的时候如果直接输出异常对象,那么所获得的异常信息是不完整的
e.printStackTrace(); // 输出异常信息
} finally {
System.out.println("【FINALLY】不管是否出现异常,都会执行本操作。");
}
System.out.println("【计算结束】----------");
}
}
程序执行结果:
java.lang.ArithmeticException: / by zero
at org.example.exceptionHandling.TestException.main(TestException.java:20)
【FINALLY】不管是否出现异常,都会执行本操作。
【计算结束】----------将上面的改成 result = 10 / 1;
程序执行结果:
【计算结果】10
【FINALLY】不管是否出现异常,都会执行本操作。
【计算结束】----------
通过以上的异常处理格式的使用,就可以保证程序的正常执行完毕,并且不会再出现因为异常而中断的问题。
4 处理多个异常
如果当前的程序中会同时存在有三种可能产生的异常:算数异常(ArithmeticException)、数组越界异常(ArayIndexOutOfBoundsException)、数字格式化异常(NumberFormatException),而整个的程序里面由于catch语句中仅仅捕获了一个算术异常〈ArithneticException),那么其余的异常由于都没有正常处理,所以程序都直接退出了(没有正确执行完毕),所以对于本程序来讲最后一条输出信息在没有正确处理异常的时候就不会输出了。如果要想保证当前的程序都可以正常的执行完毕,那么就需要在程序代码之中进行多个异常的处理。
5 异常处理流程
算数异常:
数字格式化异常:
- java.lang.Object
- java.lang.Throwable
- java.lang.Exception
- java.lang.RuntimeException
- java.lang.ArithmeticException
- java.lang.Object
- java.lang.Throwable
- java.lang.Exception
- java.lang.RuntimeException
- java.lang.IllegalArgumentException
- java.lang.NumberFormatException
通过以上异常类的继承结构可以发现,所有的异常类实际上都属于Throwable 的子类。而在Throwable类中实际上会存在有两种子类 Error、Exception,这两个子类区别如下:。
Error:指的是JVM错误,一般来讲大部分的错误都是发生在JVM运行的过程之中,这种错误无法通过程序处理;
Exception:指的是程序执行的过程之中产生的异常,可以通过程序来进行处理;程序中绝大多数可以处理的异常都是Exception子类。
1、在程序代码编写程之中,由于处理逻辑的不到位,那么有可能会让代码产生异常,例如“10/0”那么就表示有异常了;
2、当异常产生之后会由JVM根据异常的类型而自动的实例化一个异常类的对象(控制异常对象的个数对性能提升非常有必要);
3、如果当前的程序代码之中已经明确的提供了异常处理语句的格式,那么就对异常进行捕获,如果没有提供异常处理语句,那么会自动的将此异常对象交由JVM进行默认的处理,而默认的处理方式为:输出异常信息,同时中断程序的执行;
4、如果此时的代码中存在有异常处理结构,则会通过try语句捕获当前的异常类的实例化对象,同时对于异常产生之后的代码也将不再继续执行;
5、如果在try 语句之后定义有catch语句,那么会自动利用捕获到的实例化对象与catch 中捕获的异常类型进行匹配,如果匹配成功则使用当前的catch进行异常处理,如果匹配不成功,则交由下一个的catch继续匹配;
6、不管是否存在有匹配的catch的异常类型,最终都要执行finally中的代码,但是如果已经处理过的异常则可以继续向下执行其他的操作代码,而如果没有处理过的异常,那么就表示当前的异常处理结构无法处理此异常,则会交由JVM进行默认处理;
清楚了整个的异常处理流程之后,实际上就会发现所谓的异常捕获和匹配就属于对象与类之间的匹配关系,实际上这种做法和instanceof的作用是相的。
异常类对象=new异常类(); // 由JVM负责实例化
if(对象 instanceof类) { // catch 匹配
处理异常
}
按照面向对象的设计的要求来讲,所有的子类都可以自动的向父类对象进行转换,也就是说只要现在在 catch 语句中使Exception类型,那么就可以处理全部的异常了。
6 throws关键字
在Java中就提供了一个 throws关键字(仅仅能够出现在方法的定义上),这个关键字的主要功能是针对于某些操作的方法上可能抛出的异常进行声明。
7 throw关键字
在之前所有见到的异常实际上都是由JVM自动负责实例化处理的,但是并不是所有的异常都会自动化进行异常对象实例化,因为有一些异常是需要产生了某些问题之后才有可能出现,所以此时在Java中就提供有一种手工实例化异常异常类的操作功能,而这个功能就必须通过throw关键字来完成,这个关键字的主要的作用就是实现异常对象的抛出。
总结: throw 与 throws关键字?
throw的主要功能描述的是手工进行异常的抛出,一般系统中的手工异常抛出都是需要结合分支判断处理的
throws它的功能是明确的告诉用户某个方法上有可能会产生怎样的异常,方便用户进行处理。