首页 > 其他 > 详细

第9节 异常

时间:2019-03-23 19:22:50      阅读:129      评论:0      收藏:0      [点我收藏+]

一、认识异常

  异常是指在程序运行过程中所发生的不正常事件,如文件找不到、网络连接不通或链接中断、算数运算出错、数组下标越界、装在一个不存在的类、对null对象操作、类型转换异常等。异常会中断正在运行的程序。

package com.moreException;
import java.util.Scanner;
/**
 * 演示程序中的异常。
 * @author yu
 */
public class Test1 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("请输入被除数:");
        int num1 = in.nextInt();
        System.out.print("请输入除数:");
        int num2 = in.nextInt();
        System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
        System.out.println("感谢使用本程序!");
    }
}

  技术分享图片        技术分享图片

  此时,可以通过增加if-else语句对各种异常情况进行判断处理:

package com.moreException;
import java.util.Scanner;
/**
 * 传统处理程序中的异常。
 * @author 北大青鸟
 */
public class Test1{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("请输入被除数:");
        int num1 = in.nextInt();
        System.out.print("请输入除数:");
        int num2 = 0;
        if (in.hasNextInt()) { // 如果输入的除数是整数
            num2 = in.nextInt();
            if (0 == num2) { // 如果输入的除数是0
                System.err.println("输入的除数是0,程序退出。");
                System.exit(1);
            }
            System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
            System.out.println("感谢使用本程序!");
        } else { // 如果输入的除数不是整数
            System.err.println("输入的除数不是整数,程序退出。");
            System.exit(1);
        }

    }
}

  技术分享图片   技术分享图片

  if-else语句进行异常处理,有很多缺点:代码臃肿、异常处理代码占用时间精力,影响开发效率、很难列举所有的异常情况、影响代码可读性

二、Java异常体系结构

  技术分享图片

  异常在Java中被封装成了各种异常类,所有的异常类都是Throwable类的子类,它派生了2个子类:Error类和Exception类。

  1)Error类:表示依靠程序本身无法恢复的严重错误,如内存溢出、动态链接失败、虚拟机错误等。出现这种错误,应尽力使应用程序安全退出

  2)Exception类:有java程序抛出和处理的非严重性错误,如算数运算出错、数组下标越界等。Exception类又可分为2大类异常:

    1.运行时异常:包括RuntimeException及其所有子类,如算数异常ArithmeticException

    2.Checked异常(非运行时异常):除了运行时异常外的其他从Exception继承来的异常类。

  常见异常:  

    算术异常类:ArithmeticExecption

    空指针异常类:NullPointerException

    类型强制转换异常:ClassCastException

    数组负下标异常:NegativeArrayException

    数组下标越界异常:ArrayIndexOutOfBoundsException

    违背安全原则异常:SecturityException

    文件已结束异常:EOFException

    文件未找到异常:FileNotFoundException

    字符串转换为数字异常:NumberFormatException

    操作数据库异常:SQLException

    输入输出异常:IOException

    方法未找到异常:NoSuchMethodException

 三、Java异常处理机制

  1.异常处理:通过5个关键字来实现,try  catch  finally  throw  throws

  2.使用try-catch处理异常

package cn.yu.exception;
import java.util.Scanner;
/**
 * 使用try-catch进行异常处理。
 * @author yu
 */
public class Test3 {
    public static void main(String[] args) {
	    Scanner in = new Scanner(System.in);
            System.out.print("请输入被除数:");        
	    try {
               int num1 = in.nextInt();
               System.out.print("请输入除数:");
               int num2 = in.nextInt();
               System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
               System.out.println("感谢使用本程序!");
            } catch (Exception e) {
               System.err.println("出现错误:被除数和除数必须是整数,除数不能为零。");
               e.printStackTrace();
        }
    }
}

  try-catch语句块的执行流程比较简单,首先执行try语句块中代码,这时会有3种情况:

    1)try语句块所有代码正常执行完毕,将不会执行catch语句块中代码

       2)try语句块在执行过程中出现异常,并且这个异常与catch语句块中声明的异常类型匹配,那么try语句块中剩余代码将被忽略不再执行,而相应的catch语句块中代码将会被执行

    3)try语句块在执行过程中出现异常,并且这个异常与catch语句块中声明的异常类型不匹配,那么方法立刻退出

   在catch语句块中可以加入用户自定义处理信息,也可以调用异常对象的方法输出异常信息。
   常用异常信息打印方法:

    1)getMessage(): String 输出异常的描述信息

       2)getLocalizedMessage() 输出本地化的描述信息,一般此方法可被子类所覆盖,缺省实现与getMessage()输出信息一致

    3)printStackTrace() 将异常栈打印到输出流中,此为一类方法,默认打印到console控制台,也可以显式指定输出流。

    4)fillInStackTrace() 将当前的异常栈保存到一个Throwable中,返回这个Throwable。大部分情况下,用在保留异常栈嵌套调用的情况,尝试保留完整的异常栈,无需使用该方法。

   3.使用try-catch-finally处理异常

  此结构中try必选,catch和finally可选,但后2者必须存在其一。无论是否发生异常,finally语句块总会被执行。
  特别注意:
    1)即使在catch语句块中存在return语句,finally语句块也会执行,发生异常时执行顺序:try语句块-->catch语句块return之前的语句-->finally语句块-->执行return语句退出

    2)finally语句唯一不执行的情况是在异常处理代码中执行了System.exit()退出java虚拟机

package cn.yu.exception;
import java.util.Scanner;
/**
 * 使用try-catch-finally进行异常处理。
 * @author yu
 */
public class Test4 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("请输入被除数:");
        try {
            int num1 = in.nextInt();
            System.out.print("请输入除数:");
            int num2 = in.nextInt();
            System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
            return; //finally语句块仍旧会执行
        } catch (Exception e) {
            System.err.println("出现错误:被除数和除数必须是整数,除数不能为零。");
            //System.exit(1); // finally语句块不执行的唯一情况
            return; //finally语句块仍旧会执行
        } finally {
            System.out.println("感谢使用本程序!");
        }
    }
}

  4.使用多重catch处理异常

  可以再try语句块后跟多个catch语句块分别处理不同的异常,但排列顺序必须是从子类到父类,最后一个一般都是Exception类。

package cn.yu.exception;
import java.util.Scanner;
import java.util.InputMismatchException;
/**
 * 多重catch块
 * @author yu
 */
public class Test6 {
  public static void main(String[] args) {
      Scanner in = new Scanner(System.in);
      System.out.print("请输入被除数:");
	  	try {
          int num1 = in.nextInt();
          System.out.print("请输入除数:");
          int num2 = in.nextInt();
          System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
      } catch (InputMismatchException e) {
          System.err.println("被除数和除数必须是整数。");
      } catch (ArithmeticException e) {
          System.err.println("除数不能为零。");
      } catch (Exception e) {  //该异常捕捉在前,报错
          System.err.println("其他未知异常。");
      } finally {
          System.out.println("感谢使用本程序!");
      }
   }
}

  5.使用throws声明抛出异常

  如果在一个方法体中抛出了异常,并希望调用者能及时地捕获异常,可以用throws关键字声明某个方法可能抛出的各种异来通知调用者。

  通过throws声明异常,若果调用者不知道如何处理异常,可以继续通过throws声明异常,让上一级调用者处理异常。main()方法声明的异常由Java虚拟机处理。

package cn.yu.exception;
import java.util.Scanner;
/**
 * 使用throws声明异常。
 * @author yu
 */
public class Test7 {
    /**
     * 通过try-catch捕获并处理异常。
     * @param args
     */
    public static void main(String[] args) {
        try {
            divide();
        } catch (Exception e) {
            System.err.println("出现错误:被除数和除数必须是整数,除数不能为零");
            e.printStackTrace();
        }
    }
//  /**
//   * 通过throws继续声明异常。
//   */
//  public static void main(String[] args) throws Exception {  //main()方法声明的异常由Java虚拟机处理
//      divide();
//  }

    /**
     * 输入被除数和除数,计算商并输出。
     * @throws Exception
     */
    public static void divide() throws Exception {
        Scanner in = new Scanner(System.in);
        System.out.print("请输入被除数:");
        int num1 = in.nextInt();
        System.out.print("请输入除数:");
        int num2 = in.nextInt();
        System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
    }
}

    技术分享图片     技术分享图片

  6.使用throw抛出异常

   除了系统自动抛出异常外,在编程过程中有些问题是体统无法自动发现并解决的,如性别输入不是”男”或“女”,此时要把问题提交给调用者去处理。

  可以使用throw关键字来自行抛出异常。 

package cn.yu.exception;
/**
 * 使用throw在方法内抛出异常。
 * @author yu
 */
public class Person {
	private String name = "";// 姓名
	private int age = 0;// 年龄
	private String sex = "男";// 性别
	/**
	 * 设置性别。
	 * @param sex 性别
	 * @throws Exception
	 */
	public void setSex(String sex) throws Exception {
		if ("男".equals(sex) || "女".equals(sex))
			this.sex = sex;
		else {
			throw new Exception("性别必须是“男”或者“女”!");  //抛出异常给调用者
		}
	}
	/**
	 * 打印基本信息。
	 */
	public void print() {
		System.out.println(this.name + "(" + this.sex 
				+ "," + this.age + "岁)");
	}
}

  

package com.moreException;
/**
 * 捕获throw抛出的异常。
 * @author yu
 */
public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        try {
            person.setSex("Male");
            person.print();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

  技术分享图片

  throws和throw区别:

  • 作用不同:throw用于程序员自行产生并抛出依会场,throws用于声明该方法内部抛出了异常
  • 使用的位置不同: throw位于方法体内部,可以作为单独语句使用;throws必须跟在方法参数列表后面,不能单独使用
  • 内容不同:throw抛出一个异常对象,只能是一个;throws后面跟异常类,可以跟多个

  7.自定义异常

  步骤:

    1)定义异常类,并继承Exception类或者RuntimeException类

    2)编写异常类的"构造方法",并继承弗父类的实现

    3)实例化自定义异常对象,并在程序汇总使用throw抛出

package com.moreException;
/*
* 自定义异常类
*/
public class GenderException extends Exception{
    //构造方法(常用4种)
//    public GenderException() {
//        super();
//    }
    public GenderException(String message) {
        super(message);
    }
//    public GenderException(String message,Throwable cause) {
//        super(message,cause);
//    }
//
//    public GenderException(Throwable cause) {
//        super(cause);
//    }

}

  

package com.moreException;

class Person{
    private String name="";			//姓名
    private int age=0;				//年龄
    private String sex="男";		//性别
    //设置性别
    public void setSex(String sex) throws GenderException {
        if ("男".equals(sex) || "女".equals(sex))
            this.sex = sex;
        else {
            throw new GenderException("性别必须是“男”或者“女”!");
        }
    }

    //打印基本信息
    public void print(){
        System.out.println(this.name+"("+this.sex+","+this.age+"岁)");
    }
}
public class Test01{
    public static void main(String[] args){
        Person person = new Person();
        try {
            person.setSex("Male");
            person.print();
        } catch (GenderException e) {
            e.printStackTrace();
        }

    }
}

  技术分享图片

  8.异常链

  在异常处理时有时会遇到如下情况:A方法调用B方法是B方法却抛出了异常,那么A方法是继续抛出原有的异常还是跑出一个新的异常?JDK1.4退出了异常链,正好解决了这个问题,他虽创建了新的异常,但去却保留了原有异常的信息。

 

第9节 异常

原文:https://www.cnblogs.com/yutianbao/p/10562300.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!