首页 > 编程语言 >JavaSE--异常处理机制

JavaSE--异常处理机制

时间:2023-08-15 22:01:49浏览次数:56  
标签:-- System public catch println JavaSE 异常 机制 out

一、异常exception

1、什么是异常,以及Java提供的异常处理机制

  程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常

  java语言提供了异常的处理方式,如果程序执行过程中出现了不正常情况,

  java把该异常信息打印输出到控制台,供程序员参考。程序员看到异常信息之后,可以对程序进行修改,让程序更加的健壮

2、异常以类和对象的形式存在

  异常在Java中以类的形式存在,每一个异常类都可以创建异常对象

// 通过“异常类”实例化“异常对象”
NumberFormatException nfe = new NumberFormatException("数字格式化异常!");
// java.lang.NumberFormatException: 数字格式化异常!
System.out.println(nfe);

// 通过“异常类”创建“异常对象”
NullPointerException npe = new NullPointerException("空指针异常发生了!");
//java.lang.NullPointerException: 空指针异常发生了!
System.out.println(npe);

3、遇到异常,Java会自己new对象

 /*
  程序在这里除以0,
  发生了ArithmeticException异常,
  底层new了一个ArithmeticException异常对象,
  然后抛出了,由于是main方法调用了100 / 0,
  所以这个异常ArithmeticException抛给了main方法,
  main方法没有处理,将这个异常自动抛给了JVM。VM最终终止程序的执行。

        ArithmeticException 继承 RuntimeException,属于运行时异常。
        在编写程序阶段不需要对这种异常进行预先的处理。
*/
System.out.println(100 / 0);

// 这里的HelloWorld没有输出,没有执行。
System.out.println("Hello World!");

 

二、异常处理机制

1、异常的处理结构

Throwable继承自Object超类
// Throwable(可抛出的) 不管是错误还是异常都是可以抛出的
Error和Exception继承自Throwable
// Error是错误类,只要有错误发生,Java程序只有一个结果,就是终止程序执行,退出jvm
// 错误是不能处理的

// Exception是异常类
Exception分为:Exception的直接子类、RuntimeException

编译时异常
所有Exception的直接子类,都叫做编译时异常。编译时异常不是在编译阶段发生的
编译时异常是表示必须在编写程序的时候预先对这种异常进行处理,如果不处理编译器报错。

运行时异常
所有的RuntimeException及子类都属于运行时异常。运行时异常在编写程序阶段,你可以选择处理,也可以不处理。

 2、编译时异常和运行时异常的区别

编译时异常发生概率高,编译时异常又被称为受检异常或者受控异常

运行时异常发生概率低,运行时异常又被称为未受检异常或者未受控异常

注意::所有异常都是发生在运行阶段的

3、异常处理的两种方式

  1)第一种方式:

    在方法声明位置上,使用throws关键字看,抛给上一级(异常的上抛)

    谁调用我就抛给谁

    注意:一般不建议抛给main方法,main方法中最好使用try catch

public class ExceptionTest04 {
    public static void main(String[] args) {
        // main方法中调用doSome()方法
        // 因为doSome()方法声明位置上有:throws ClassNotFoundException
        // 我们在调用doSome()方法的时候必须对这种异常进行预先的处理。
        // 如果不处理,编译器就报错
        //编译器报错信息: Unhandled exception: java.lang.ClassNotFoundException
        doSome();// 编译时报错
    }

    /**
     * doSome方法在方法声明的位置上使用了:throws ClassNotFoundException
     * 这个代码表示doSome()方法在执行过程中,有可能会出现ClassNotFoundException异常。
     * 叫做类没找到异常。这个异常直接父类是:Exception,所以ClassNotFoundException属于编译时异常。
     * @throws ClassNotFoundException
     */
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome!!!!");
    }

}
// 第一种:使用throw关键字
public class ExceptionTest04 {
    // 抛给调用者
    public static void main(String[] args) throws ClassNotFoundException{
        doSome();
    }
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome!!!!");
    }

}

注意注意:throws抛异常时可以抛出该异常,也可以抛出该异常的父类异常,也可以抛出所有异常

// 抛FileNotFoundException的父对象IOException,这样是可以的。因为IOException包括FileNotFoundException
private static void m2() throws IOException {

// Exception包括所有的异常
private static void m2() throws Exception{
    
// throws后面也可以写多个异常,可以使用逗号隔开。
private static void m2() throws ClassCastException, FileNotFoundException{

  1)第二种方式:

    使用try... catch语句进行异常的捕捉(异常的捕捉)

注意:Java中 异常发生之后如果一直上抛,最终抛给了main方法,main方法继续向上抛,抛给了调用者JVM,JVM知道这个异常发生,只有一个结果:终止java程序的执行。

// 第二种try...catch
public static void main(String[] args) {
    try {
        // 尝试
        doSome();
    } catch (ClassNotFoundException e) {// e是为这个异常取的名字
        // catch是捕捉到异常之后走的分支
        System.out.println("类没有发现异常");
        e.printStackTrace();
    }
}

    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome!!!!");
    }
}

注意注意:只要异常没有捕捉,采用上报的方式,此方法的后续代码不会执行。另外需要注意,try语句块中的某一行出现异常,该行后面的代码不会执行

4、try...catch的深入了解

  1)catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型,也可以抛出Exception

  2)catch可以写多个。建议catch的时候,精确的一个一个处理。这样有利于程序的调试

  3)catch写多个的时候,从上到下,必须遵守从小到大

public class ExceptionTest07 {

    public static void main(String[] args) {
        try {
            //创建输入流
            FileInputStream fis = new FileInputStream("D:document\\风格.pdf");
            //读文件
            fis.read();
        } catch(FileNotFoundException e) {
            System.out.println("文件不存在!");
        } catch(IOException e){
            System.out.println("读文件报错了!");
        }
 
    }
}
 // JDK8的新特性
// 可以 或 异常,这个异常或者那个异常
try {
    //创建输入流
    FileInputStream fis = new FileInputStream("D:\\curse\\02-JavaSE\\document\\JavaSE进阶讲义\\JavaSE进阶-01-面向对象.pdf");
    // 进行数学运算
    System.out.println(100 / 0);
    // 这里这些异常可以 或
} catch(FileNotFoundException | ArithmeticException | NullPointerException e) {
    System.out.println("文件不存在?数学异常?空指针异常?都有可能!");
}

5、上抛和捕捉怎么选择

  如果希望调用者来处理,就使用上抛。其他情况使用捕捉

6、异常对象常用方法

获取异常简单的描述信息:
    String msg = exception.getMessage();

打印异常追踪的堆栈信息:
    exception.printStackTrace();
// 这里只是为了测试getMessage()方法和printStackTrace()方法。
// 这里只是new了异常对象,但是没有将异常对象抛出。JVM会认为这是一个普通的java对象。
NullPointerException e = new NullPointerException("空指针异常");

// 获取异常简单描述信息:这个信息实际上就是构造方法上面String参数。
String msg = e.getMessage(); //空指针异常
System.out.println(msg);

// 打印异常堆栈信息
// java后台打印异常堆栈追踪信息的时候,采用了异步线程的方式打印的。
e.printStackTrace();

7、try catch中finally关键字

  1)

    在finally自居中的代码时最后执行的,并且一定会执行的,即使try语句块中的代码出现异常

    必须和try catch一起使用

  2)finally语句通常使用在哪些情况下

    通常在finally语句块中完成资源的释放/关闭。

    因为finally中的代码比较有保障。即使try语句块中的代码出现异常,finally中代码也会正常执行。

  3)退出jvm之后finally就不执行了

System.exit(0);

 

public class ExceptionTest10 {
    public static void main(String[] args) {
        FileInputStream fis = null; // 声明位置放到try外面。这样在finally中才能用。
        try {
            // 创建输入流对象
            fis = new FileInputStream("D:\\JavaSE进阶-01-面向对象.pdf");
            // 开始读文件....

            String s = null;
            // 这里一定会出现空指针异常!
            s.toString();
            System.out.println("hello world!");

            // 流使用完需要关闭,因为流是占用资源的。
            // 即使以上程序出现异常,流也必须要关闭!
            // 放在这里有可能流关不了。
            //fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch(IOException e){
            e.printStackTrace();
        } catch(NullPointerException e) {
            e.printStackTrace();
        } finally {
            System.out.println("hello 浩克!");
            // 流的关闭放在这里比较保险。
            // finally中的代码是一定会执行的。
            // 即使try中出现了异常!
            if (fis ! = null) { // 注意注意::避免空指针异常
                try {
                    // close()方法有异常,采用捕捉的方式。
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        System.out.println("hello kitty!");

    }
}

 

三、自定义异常

1、为什么自定义异常

  SUN提供的JDK内置的异常肯定是不够的用的

  在实际的开发中,有很多业务,这些业务出现异常之后,JDK中都是没有的和业务挂钩的。那么异常类我们可以自己定义

2、怎么定义异常

  第一步:编写一个类继承Exception或者RuntimeException

  第二步:提供两个构造方法,一个无参数的,一个带有String参数的

// 就是这样的结构,这样写就行,根据sun公司的源代码来这样写
public class MyException extends Exception{ // 编译时异常
    public MyException(){

    }
    public MyException(String s){
        super(s);
    }
}
/*
public class MyException extends RuntimeException{ // 运行时异常

}
 */

 

public class ExceptionTest15 {
    public static void main(String[] args) {

        // 创建异常对象(只new了异常对象,并没有手动抛出)
        MyException e = new MyException("用户名不能为空!");

        // 打印异常堆栈信息
        e.printStackTrace();

        // 获取异常简单描述信息
        String msg = e.getMessage();
        System.out.println(msg);
    }
}

3、怎么使用自定义异常

  trow手动抛出异常

// 先定义一个异常
/**
 * 栈操作异常:自定义异常
 */
public class MyStackOperationException extends Exception{ // 编译时异常

    public MyStackOperationException(){

    }

    public MyStackOperationException(String s){
        super(s);
    }

}
// 一个模拟栈的类
// 其中的一个方法
 /**
     * 压栈的方法
     * @param obj 被压入的元素
     */
    public void push(Object obj) throws MyStackOperationException {
        if(index >= elements.length - 1){
            /*  栈满了 这也算是一个异常,那我们就可以自定一个异常类来这个让我们使用
                以前的写法
                System.out.println("压栈失败,栈已满");
                return;
            */
            // 创建异常对象
            //MyStackOperationException e = new MyStackOperationException("压栈失败,栈已满!");
            // 手动将异常抛出去!
            //throw e; //这里捕捉没有意义,自己new一个异常,自己捉,没有意义。栈已满这个信息你需要传递出去。

            // 合并
            throw new MyStackOperationException("压栈失败,栈已满!");
        }
        index++;
        elements[index] = obj;
        System.out.println("压栈" + obj + "元素成功,栈帧指向" + index);
    }

 

标签:--,System,public,catch,println,JavaSE,异常,机制,out
From: https://www.cnblogs.com/hyy-0/p/17621849.html

相关文章

  • JAVA向Mysql插入亿级数量数据各种方式效率对比
    研究mysql优化中查询效率,通过随机生成人的姓名、年龄、性别、电话、email、地址,向mysql数据库大量插入数据,便于用大量的数据测试SQL语句优化效率。生成过程中发现使用不同的方法,效率天差万别。1、先上Mysql数据库,随机生成的人员数据图。分别是ID、姓名、性别、年龄、Email、电话......
  • PCBA加工厂发货要如何做好运输保护?
    PCBA加工完成之后,在出货运输过程中PCBA板可能会受到颠簸、碰撞、摩擦等各种因素的影响,那我们怎么做好保护措施呢?PCBA在经过SMT贴片加工、插件、组装测试等各种加工过程后就要面临发货的问题,在发货的运输过程中需要注意是下面的几个方面。1、包装材料PCBA是比较脆弱并且容易被损坏的......
  • Python教程(9)——Python变量类型列表list的用法介绍
    (目录)在Python中,列表(list)是一种有序、可变的数据结构,用于存储多个元素。列表可以包含不同类型的元素,包括整数、浮点数、字符串等。实际上列表有点类似C++语言中的数组,但仅仅只是类似,和数组还是有点不一样的。列表非常适合利用顺序和位置定位某一元素,尤其是当元素的顺序或内容经常......
  • java中对无参构造和有参构造的理解
    构造器的最大作用就是在创建对象时,对对象实例进行初始化。1.一个类即使什么都不写,也会存在无参构造方法。2.无参构造方法没有返回值类型,且方法名称和类名相同。比如:1publicclassStudent{2privateStringname;3privateintage;45publicvoidst......
  • TFTP协议的历史及其工作原理
    TFTP(TrivialFileTransferProtocol)协议的历史可以追溯到1981年,当时它被作为简单文件传输协议在ARPANET中标准化。TFTP协议被设计得非常简单,因此它可以在不消耗计算机资源的情况下进行文件传输。1982年,TFTP协议被指定为标准RFC783。在随后的几年中,TFTP协议得到了进一步的发展和改......
  • ARC161
    ARC161A排序后直接奇偶分类地填即可#include<bits/stdc++.h>usingnamespacestd;constintMAXN=2e5+5;intn;inta[MAXN];intb[MAXN];intmain(){//freopen("date.in","r",stdin);//freopen("date.out","w",stdout......
  • 中国注册会计师-经济法
    第一章法律的基本原理:法的基本概念法的概念与特点1、法的产生方式:国家制定或认可2、法的实施:社会主体自觉遵守,只有不遵守时,国家强制力保障实施3、法的本质:统治阶级意志的体现、统治阶级整体意志、物质生活条件决定的4、法的性质:法律规范属于社会规范5、确定社会关系参加者的权利和......
  • go语言编程常见问题
    在Goland中运行单元测试报错Error:Cannotfindpackage如下图,在Goland中运行单元测试时报错:“Error:Cannotfindpackage”弹出如下报错提示窗口:解决办法:在Goland设置界面中取消勾选“EnableGomodulesintegration”。参考:goland中运行go时报packagexxxisnotinGO......
  • [COCI2015-2016#7] Prokletnik
    [COCI2015-2016#7]Prokletnik有那么一点点启发性。假设右端点是最大值,思路很简单很经典,考虑扫描线+线段树,那么修改涉及到的点就是当前的后缀最小值,维护一个单调不减的单调栈,那么单调栈里面的点都要改。难道我们要遍历单调栈吗?哈哈,并不用,我们直接在单调栈上面建一棵线段树就行......
  • 《Lua程序设计第四版》 第二部分14~17章自做练习题答案
    Lua程序设计第四版第二部分编程实操自做练习题答案,带⭐为重点。14.1⭐该函数用于两个稀疏矩阵相加functionmartixAdd(a,b)localc={}fori=1,#a,1doc[i]={}fork,vinpairs(a[i])doc[i][k]=vendend......