zoukankan      html  css  js  c++  java
  • JAVA异常与异常处理

    第一节 JAVA异常简介

    程序中阻止当前方法或作用域继续执行的问题,我们就把它称作异常。所有异常类的鼻祖是Throwable类,该类分成两个,分别是Error类和Exception类。Error一般是虚拟机错误或者线程死锁,系统错误内存溢出。这里我们主要讨论后者,Exception是编码、环境、用户操作、输入出现问题。主要分为RuntimeException(非检查异常,运行时异常)和检查异常以及其他各种异常。异常可以提示程序员出现错误,使中断的程序能够以适当的方式运行;或者保存用户操作进行数据回滚;退出;fanilly及时回收占用资源。
    常见的非检查异常有四种:空指针异常 NullPointerException,数组下标越界异常 ArrayIndexOutOfBoundsException, 类型转换异常 ClasslastException,算数异常 ArithmeticException。这是在今天做练习时遇到的一种异常:欲得到的数据类型与实际输入的类型不匹配 InputMismatchException。
    非检查异常就是运行时异常,引起非检查异常的原因有很多:比如说引用了一个空对象的属性或者方法;也有可能是数组访问越界,或者是一个错误的类型转换,以及可能是算数引起的异常比如整数除以0,0不能作为除数。除了这四种还有很多其他运行时异常,都是RuntimeExcepetion的子类,运行时异常会由java虚拟机自动抛出自动捕获。检查异常与RuntimeException不同,必须要声明并手动添加语句捕获处理,一般是文件异常或者sql异常 IOException SQLException 文件不存在或是连接错误。相反的,继承自 RuntimeException 的异常可以不需要进行声明。

    第二节 处理异常

    一般用try-catch或者try-catch-finally捕获并处理异常。
    try{//一些会抛出异常的方法}catch(异常类型Exception e){//处理该异常的代码块}
    try抛出异常,catch捕获处理相应的异常代码块。如果try块中的方法确实会抛出异常,方法会终止执行,然后程序的控制权会交由catch块中的异常处理程序去处理,catch块中的语句该如何写呢,则是根据不同的业务情景不同对待,比如可以向用户或者编程人员发出警告,去检查配置以及网络连接,或者也可以在catch语句块中进行错误日志这样的操作。
    多重catch

    try{//一些会抛出异常的方法
    }catch(Exception e){//处理该异常的代码块
    }catch(Exception2 e){//处理异常2的代码块
    }catch(Exception3 e){//处理异常3的代码块
    }...(N个catch块)}finally{最终将要执行的一些代码,善后工作}
    

    关于catch块中的异常编写先后顺序问题,先子后父,先小后大,先子类后父类来编写catc块中的异常语句。

    第三节 try-catch案例

    e.printStackTrace();输出异常的位置类型信息原因
    e.toString();输出异常类型及异常信息
    e.getMessage();输出异常信息
    在这里值得注意的是如果定义的是一个有返回值的方法,比如public int test(){},try块和catch块中都要有return返回值或者,在这两个代码结束的最后返回一个int类型的值,mian函数调用方法时可以新建变量去接收这个返回值。

    第四节 JAVA中的异常抛出及自定义异常类

    throw 将产生的异常抛出,这是一个动词。throws 也叫声明异常,写在方法名和方法的参数列表之后,在方法体之前,用它修饰的方法,向调用者表明该方法可能会抛出某种类型的异常,可以抛出一种或多种,用逗号隔开。然后具体的方法里可以调用一些会抛出异常的方法,或者可以先抛出一个异常,这里就用到了throw关键字。
    public void test()throws异常列表,逗号隔开{
    //1、调用会抛出异常的方法,2、或者先抛出一个异常,throw new Exception();}
    throw写在方法体里边代表一个具体的抛出异常的动作
    自定义异常:
    class自定义异常类 extents 异常类型{
    //添加有参构造器
    public 自定义异常类(String message){super(message)}
    //添加无参构造器
    public 自定义异常类(){ }
    }
    继承的必须是相近的类库异常或者是所有异常类型的基类Exception,异常处理不了时可以交由调用它的上级去处理。

    第五节 java中的异常链

    有时候可以把捕获的异常包装成一个新的异常,然后在新的异常里添加一个对原始异常的引用,再把这个新异常抛出,就像链式反应一样,一个导致另一个。
    异常链的两种写法:一种是initcause(e)调用initcause方法把参数异常传递进去,这个是定义原始异常。另一种是简便写法RuntimeException e2=new RuntimeException(e);使用第一种方法时,也一样要新建一个RuntimeException();只是没有参数。
    例题是把喝大了这个自定义异常包装成运行时异常然后抛出,在main方法中捕获,这就是异常链。编写第一个方法直接抛出异常喝大了,方法二中调用1方法,因为1会抛出异常,所以要用try catch语句块进行包围。

    public void test2(){
    try{test1();}catch(DrunkException e){
    RuntimeException e2=new RuntimeException();
    e2.inItcause(e);  //RuntimeException e2=new RuntimeException(e);
    throw  e2;抛出异常 
    }}
    

    在这里需要注意的是test1方法必须写throws声明异常,test2却不用,这是由于Exception包括非检查性异常RuntimeException和检查性异常如:IOException之类,两种异常的区别:
    非检查性异常及子类,程序中可以不处理,但是运行时会报异常.
    检查性异常及子类,程序中必须处理,其它一样.
    所以,RunTimeException异常是不需要throws的,程序中无需处理,throws一下也没事,//尝试过没有报错
    initCause();定义原始异常,这里也就是说该运行时异常的原始异常:喝大了异常DrunkException

    第六节 实际应用中的经验总结

    1.处理运行异常时,采用逻辑去合理规避,优化代码的同时,辅助try-catch去处理;
    2.在多重catch块后面,我们还可以加一个catch(Exception e)来处理可能会被遗漏的异常;
    3.对于不确定是否会抛出异常的代码,可以加上try-catch,处理潜在的异常;
    4.尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出;
    5.具体如何处理异常,要根据不同的业务需求和异常类型去决定;
    6.尽量添加finally语句块去释放占用的资源,有其是在网络连接和连接数据库的情况下。

    留下的练习题使用到的知识点
    练习题是模拟图书馆借书。
    For循环遍历数组内容;
    equals比较字符串是否一样;
    While(true)循环,可以先定义一个boolean变量为true,出现某个结果想要结束循环时可以给它复制false;
    try-catch放在循环体内部还是外部。这次的练习是输入图书的序号或者书名来确认书是否存在,一共可能出现两个异常,第一个是该输入数字的时候输入字符串InputMismatchException还有一个异常是数组下标访问越界异常ArrayIndexOutOfBoundsException。练习的要求主要是做一个数组存放书,然后借取的时候如果输入不匹配的信息会如何报错,写出来的代码也顺便放在这留做纪念吧:

    package trycatch.JieShuXiTong;
    import java.util.InputMismatchException;
    import java.util.Scanner;
    /**
     * Created by Administrator on 2017/3/28.
     */
    public class JieShuXiTong {
        String[] name = {"科幻世界", "空之境界", "发条女孩", "三体", "深渊上的火", "安德的游戏", "天渊", "狼人十字架", "时砂之王"};
        String[] xuHao = {"1-", "2-", "3-", "4-", "5-", "6-", "7-", "8-", "9-",};
    
        public static void main(String[] args) {
            System.out.println("您好,欢迎您的到来,目前图书馆可供借阅的图书有:");
            JieShuXiTong js = new JieShuXiTong();
            //循环遍历输出序号和书名
            for (int i = 0; i < js.name.length; i++) {
                System.out.print(js.xuHao[i]);
                System.out.print(js.name[i]);
                if (i < js.name.length - 1) System.out.print(";");
            }
            System.out.println("");
            System.out.println("请选择您查找图书的方式");
            //定义一个boolean类型的变量,初始值为true
            boolean bl=true;
            //while循环,这样当不想让他循环时给赋值成false就好了
            //给整个循环体加了try块。异常只有两种可能一种是数组遍历时越界,还有一种是类型不匹配,比如int类型你输入胡汉字
            //或者字符就不对了
            while (bl) {
                try {
                    System.out.println("输入1,按书名查找图书");
                    System.out.println("输入2,按图书序号查找图书");
                    Scanner a = new Scanner(System.in);
                    int num = a.nextInt();
                    if (num == 1) {
                        System.out.println("请输入您要查询的书的名字");
                        String name2 = a.next();
                        for (int i = 0; i < js.name.length; i++) {
                            if (name2.equals(js.name[i])) {
                                System.out.println("book:" + name2);
                                bl=false;
                                break;
                            } else if (i == js.name.length - 1) {
                                System.out.println("图书不存在或输入异常,请重新输入");
                            }
                        }
                    }else if (num == 2) {
                        System.out.println("请输入您要查询的书的号码");
                        int num2 = a.nextInt();
                        System.out.println("book:" + js.name[(num2 - 1)]);
                        bl=false;
                    }else{
                        System.out.println("您的输入有误请重新操作");
                        continue;
                    }
                } catch (InputMismatchException e) {
                    System.out.println("您的输入格式有误,请重新输入");
                } catch (ArrayIndexOutOfBoundsException e) {
                    System.out.println("您的输入的号码已超过当前最大书号,请重新输入");
                }
            }
        }
    } 
    
    乘风而归——只要抱着良好的愿望演奏,演员的演技可以不予苛求。
  • 相关阅读:
    出现“在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。”这样的错误!
    关于sql server 2008过期导致 MSSQLSERVER服务就无法启动,手动启动就报告错误代码17051。
    ASP.NET 回调技术(CallBack)
    Asp.net中的ajax回调模式(ICallbackEventHandler)
    CKEditor4.1和CKFinder2.3.1 for Mvc4最新 破解版,结合 打造"帅"的编辑器 For .Net
    .net_ckeditor+ckfinder的图片上传配置
    文件上传限制大小 dotnet/C#
    C#.Net 上传图片,限制图片大小,检查类型完整版
    图片上传代码(C#)
    C#中操作xml文件(插入节点、修改、删除)
  • 原文地址:https://www.cnblogs.com/xuejiangbo/p/6687254.html
Copyright © 2011-2022 走看看