认识异常对程序的影响
Java语言最强大的支持在于异常处理。异常是指中断程序执行的指令流。
例子:产生异常
public class Yichang {
public static void main(String[] args) {
System.out.println(10/0);
System.out.println("1234");
}
}
运行结果:
Exception in thread “main” java.lang.ArithmeticException: / by zero
at Yichang.main(Yichang.java:4)
当程序没有异常时,代码按照指令步骤执行。当存在异常时编译程序就会出现错误。出现错误之后程序就会中断执行。异常机制为了避免程序出现非致命错误导致程序中断执行。
处理异常
在Java中进行异常处理,可以使用:try、finally、catch这几个关键字来完成,其基本处理结构如下:
此结构中可以使用的组合有三种:try…catch; try…finally; try…catch…finally。
例子:对以上程序进行处理异常
public class Yichang {
public static void main(String[] args)
{
try{
System.out.println(10/0);
}catch(ArithmeticException x){
System.out.println(x);
}
System.out.println("1234");
}
}
输出结果:
java.lang.ArithmeticException: / by zero
1234
此时即使出现了异常,但是程序可以跳过异常继续执行。但是有一个问题,此时的提示信息对于错误排查不方便。为了获得完整的异常信息,则可以利用异常类中提供的printStackTrace()方法。
例子:获取完整异常现象
public class Yichang {
public static void main(String args[]) {
try{
System.out.println(10/0);
}
catch(ArithmeticException x) {
x.printStackTrace();
}
System.out.println("1234");
}
}
输出结果:
java.lang.ArithmeticException: / by zero
at Y.Yichang.main(Yichang.java:5)
1234
例子:对于异常处理也可以追加一个finally程序块,不管是否产生异常,程序中finally都执行。
public class Yichang {
public static void main(String[] args)
{
System.out.println("xfak,wa");
try{
System.out.println(10/0);
}catch(ArithmeticException x){
x.printStackTrace();
}finally{
System.out.println("jyxx,pp");
}
}
}
输出结果:
xfak,wa
java.lang.ArithmeticException: / by zero
at Yichang.main(Yichang.java:6)
jyxx,pp
处理多个异常
程序在执行过程中可能产生许多异常,这种情况下需要使用多个catch捕捉异常。
例子:
public class Yichang {
public static void main(String[] args)
{
System.out.println("xfak,wa");
try{
int x =Integer.parseInt(args [0]);
int y =Integer.parseInt(args [1]);
System.out.println(x/y);
}catch(ArithmeticException x){
x.printStackTrace();
}finally{
System.out.println("jyxx,pp");
}
}
}
此时执行程序会出现三类异常;
1·【未处理】程序执行过程时没有输入初始化参数;
[1]xfak,wa
[2]jyxx,pp
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Yichang.main(Yichang.java:6)
2·【未处理】输入的数据不是数字;
[1]xfak,wa
[2]jyxx,pp
Exception in thread "main" java.lang.NumberFormatException: For input string: "a"
at Yichang.main(Yichang.java:6)
3·【已处理】输入的被除数为零; [1]xfak,wa
java.lang.ArithmeticException: / by zero
at Yichang.main(Yichang.java:8)
[2]jyxx,pp
[3]sgg,la
即使有了异常处理语句,但是没有正确捕获异常,程序也会异常中断,finally仍然执行。
例子:多异常处理
public class Yichang {
public static void main(String[] args)
{
System.out.println("[1]xfak,wa");
try{
int x =Integer.parseInt(args [0]);
int y =Integer.parseInt(args [1]);
System.out.println(x/y);
}catch(ArithmeticException x){
x.printStackTrace();
}catch(ArrayIndexOutOfBoundsException x){
x.printStackTrace();
}catch(NumberFormatException x){
x.printStackTrace();
}finally{
System.out.println("[2]jyxx,pp");
}
System.out.println("[3]sgg,la");
}
}
异常处理流程
1、在程序运行过程中才会产生异常,一旦产生异常后将自动进行异常实例化对象;
2、若此时程序中没有提供异常支持,则进行异常打印,中断程序执行;
3、若此时程序中存在异常处理支持,那么产生的异常实例化对象会被try捕获;
4、try捕获到异常后与catch中异常类型以此对比,如此时匹配到相应异常处理,则用此catch进行异常处理;
5、如果没有匹配到任何异常处理catch,则检测是否有finally;
6、如果没有finally,则打印异常信息,中断执行。如果存在finally,则执行finally之后打印异常现象,中断程序执行。
异常处理程序之中最大的类型为Throwable,而打开Throwable可以发现存在以下两个子类:
·Error:此时程序还未执行出现的错误,开发者无法处理;
·Exception:程序中存在的异常,开发者可以处理。
通过分析发现,异常产生时候会产生异常实例化对象,异常转换可以向父类转型,实际上所有的异常都可以通过Exception处理。
例子:简化异常处理
public class Yichang {
public static void main(String[] args)
{
System.out.println("[1]xfak,wa");
try{
int x =Integer.parseInt(args [0]);
int y =Integer.parseInt(args [1]);
System.out.println(x/y);
}catch(Exception x){
x.printStackTrace();
}finally{
System.out.println("[2]jyxx,pp");
}
System.out.println("[3]sgg,la");
}
}
输出结果:
[1]xfak,wa
java.lang.ArrayIndexOutOfBoundsException: 0
at Yichang.main(Yichang.java:6)
[2]jyxx,pp
[3]sgg,la
多个异常同时处理时,捕获范围大的放后面。当不确定产生何种异常时候,如果无法确定异常,则可以使用此方法。但是如果程序模块较多,调式程序时候不管发生何种异常总是打印相同的异常信息,无法具体确认异常位置。
throws关键字
在程序执行过程中可能产生异常,但是如果说定义了一个方法,应该明确告诉使用者这个方法会产生何种异常。那么此时在方法声明上可以使用throws关键字进行异常类型标注。
例子:观察throws使用
class A{
public static int div(int x,int y)throws Exception{
return x/y;
}
}
public class Yichang {
public static void main(String[] args) {
try{
System.out.println(A.div(10,0));
}catch (Exception x){
x.printStackTrace();
}
}
}
输出结果:
java.lang.ArithmeticException: / by zero
at A.div(Yichang.java:3)
at Yichang.main(Yichang.java:9)
主方法也是方法,主方法也可以向上抛出异常。
例子:主方法抛出异常
class A{
public static int div(int x,int y)throws Exception{
return x/y;
}
}
public class Yichang {
public static void main(String[] args) throws Exception{
System.out.println(A.div(10,0));
}
}
此时不再处理异常,编译过程中如果出错由默认方式进行处理。如果主方法继续向上抛出异常,则有JVM负责处理。
throw关键字
此关键字主要作用在于手工进行异常抛出处理。
例子:观察throw使用
public class Yichang {
public static void main(String[] args) {
try{ //异常对象不再由系统生成,手工定义
throw new Exception("123456789");
}catch(Exception e){
e.printStackTrace();
}
}
}
输出结果:
java.lang.Exception: 123456789
at Yichang.main(Yichang.java:4)
throw与throws区别
1·throw是在代码块中使用的,主要是手工进行异常对象抛出;
2·throws是在方法定义上使用的,表示将此方法中可能产生的异常明确告诉给调用处,由调用出进行异常处理。
异常处理模型
定义一个出发运算方法,具体要求如下:
·在进行数学计算开始与结束时候会有信息提示;
·如果在进行计算过程中产生了异常,则要交给调用处来出来。
class A{
public static int div(int x,int y) throws Exception{
int temp = 0;
System.out.println("开始计算");
try{
temp = x/y; //出现异常,此处中断
}catch(Exception e){
throw e;//向上抛异常对象
}finally{
System.out.println("结束计算");
}
return temp;
}
}
public class Yichang {
public static void main(String[] args) {
try{
System.out.println(A.div(10,0));
}catch(Exception e){
e.printStackTrace();
}
}
}
输出结果:
开始计算
结束计算
java.lang.ArithmeticException: / by zero
at A.div(Yichang.java:6)
at Yichang.main(Yichang.java:18)
对于此类操作可以简化,省略catch与throw操作。
class A{
public static int div(int x,int y) throws Exception{
int temp = 0;
System.out.println("开始计算");
try{
temp = x/y; //出现异常,此处中断
}finally{
System.out.println("结束计算");
}
return temp;
}
}
public class Yichang {
public static void main(String[] args) {
try{
System.out.println(A.div(10,0));
}catch(Exception e){
e.printStackTrace();
}
}
}
输出结果同上。
RuntimeException
例子:观察 RuntimeException 异常继承结构。
为了方便代码编写,提供了一个可选的异常处理父类“RuntimeException”,该类的子类可以不需要强制性处理。
例子:抛出Exception 异常
class A{
public static int div(int x,int y)throws Exception{
return x/y;
}
}
public class Yichang {
public static void main(String[] args) {
System.out.println(A.div(10,0));
}
}
Yichang.java:8: 错误: 未报告的异常错误Exception; 必须对其进行捕获或声明以便抛出
System.out.println(A.div(10,0));
例子:抛出RuntimeException 子类异常
class A{
public static int div(int x,int y)throws ArithmeticException{
return x/y;
}
}
public class Yichang {
public static void main(String[] args) {
System.out.println(A.div(10,0));
}
}
Exception in thread “main” java.lang.ArithmeticException: / by zero
at A.div(Yichang.java:3)
at Yichang.main(Yichang.java:8)
** RuntimeException与 Exception区别?列举常见 RuntimeException异常。**
· RuntimeException是 Exception的子类;
· RuntimeException标注的异常不需要进行强制处理,Exception异常必须强制处理。
·列举: NumberFormatException,ClassAastException,NullPointException.
自定义异常类
Jdk提供的大量异常类型未必够使用,这个时候考虑自定义异常类。自定义异常有两种操作方法:继承Exception、继承RuntimeException
例子:观察自定义异常
class A extends Exception{ //定义异常A
public A(String a){
super(a);
}
}
class Food{
public static void eat(int num) throws A{
if (num>100){
throw new A("再吃就胖了");
}else{
System.out.println("请继续使用");
}
}
}
public class Yichang {
public static void main(String[] args) throws Exception{
Food.eat(110);
}
}
输出结果:
F:\Java学习\bao>java Yichang
Exception in thread “main” A: 再吃就胖了
at Food.eat(Yichang.java:9)
at Yichang.main(Yichang.java:17)
at Yichang.main(Yichang.java:17)
assert断言
**断言功能是指确定代码执行到某行之后是所期待的结果。**这种断言不一定是准确的,但是这种偏差不影响程序正常执行。
例子:断言的使用
public class Yichang {
public static void main(String[] args) throws Exception{
int x=100;
assert x==101 :"x值不是101";
System.out.println(x);
}
}
输出结果:100
程序正常编译执行,此时断言没有被采纳,不影响程序正常执行。在Java中并没有将断言设置为一个必须执行步骤,需要特定环境才能执行。若要想产生断言效果,必须在程序执行过程加入参数。
执行语句:java -ea Yichang
显示结果:Exception in thread “main” java.lang.AssertionError: x值不是101
at Yichang.main(Yichang.java:4)