Java异常

本文深入讲解了Java异常的概念,包括异常的发生、继承结构、编译时异常与运行时异常的区别,以及自定义异常的步骤。通过实例演示了异常捕获、抛出和finally语句的使用,以及异常对象的方法。理解异常处理有助于提高程序的健壮性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

7.异常

1.什么是异常,java提供异常处理机制有什么用?
以下程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常
java语言是很完善的语言,提供了异常的处理方式,以下程序执行过程中出现了不正常情况
java把该异常信息打印输出到控制台,供程序员参考。程序员看到异常信息之后,可以对程序进行修改,让程序更加的健壮。
什么是异常
2.以下程序执行控制台出现了
Exception in thread “main” java. Lang ArithmeticException : by zero
at com. bipowernode javase exception.ExceptionTest01 main( Exception Testo1 java: 14)
这个信息被我们称为:异常信息。这个信息是JVM打印的。

一.实例

public class ExceptionTest01 {
    public static void main(String[] args) {
        int a=10;
        int b=0;
//实际上JVM在执行到此处的时候,会new异常对象: new ArithmeticException("/ by zero")
//并且JVM将new的异常对象抛出,打印输出信息到控制台了。
        int c=a/b;
    }
}

Exception in thread “main” java.lang.ArithmeticException: / by zero
at Test01.main(Test01.java:7)

二.异常的继承结构图

在这里插入图片描述

三.编译时异常和运行时异常的区别

编译时异常一般发生的概率比较高。
举个例子:
你看到外面下雨了,倾盆大雨的。
你出门之前会预料到:如果不打伞,我可能会生病(生病是一种异常)。
而且这个异常发生的概率很高,所以我们出门之前要拿一把伞。
“拿一把伞”就是对“生病异常”发生之前的一种处理方式。
对于一些发生概率较高的异常,需要在运行之前对其进行预处理。
运行时异常一般发生的概率比较低。
举个例子:
小明走在大街上,可能会被天上的飞机轮子砸到。
被飞机轮子砸到也算一种异常。
但是这种异常发生概率较低。
在出门之前你没必要提前对这种发生概率较低的异常进行预处理。
如果你预处理这种异常,你将活的很累。
假设你在出门之前,你把能够发生的异常都预先处理,你这个人会更加
的安全,但是你这个人活的很累。
假设java中没有对异常进行划分,没有分为:编译时异常和运行时异常,
所有的异常都需要在编写程序阶段对其进行预处理,将是怎样的效果呢?
首先,如果这样的话,程序肯定是绝对的安全的。
但是程序员编写程序太累,代码到处都是处理异常的代码。
再次强调:所有异常都是发生在运行阶段的

四.异常的两种处理方式

Java语言中对异常的处理包括两种方式:
第一种方式:在方法声明的位置上,使用throws关键字,抛给上一级。
谁调用我,我就抛给谁。抛给上一级。
第二种方式**:使用try…catch语句进行异常的捕捉。**
这件事发生了,谁也不知道,因为我给抓住了。
举个例子:
我是某集团的一个销售员,因为我的失误,导致公司损失了1000元,
“损失1000元”这可以看做是一个异常发生了。我有两种处理方式,
第一种方式:我把这件事告诉我的领导【异常上抛】
第二种方式:我自己掏腰包把这个钱补上。【异常的捕捉】
张三 --> 李四 —> 王五 --> CEO
思考:
异常发生之后,如果我选择了上抛,抛给了我的调用者,调用者需要
对这个异常继续处理,那么调用者处理这个异常同样有两种处理方式。
1.8、注意**:Java中异常发生之后如果一直上抛,最终抛给了main方法,main方法继续
向上抛,抛给了调用者JVM**,JVM知道这个异常发生,只有一个结果。终止java程序的执行。

五.方法声明的地方使用throws

/*以下代码报错的原因是什么?
        因为 dosome()方法声明位置上使用了: throws ClassNotFoundException
        而ClassNot FoundException是编译时异常。必须编写代码时处理,没有处理
        编译器报错。*/
public class ExceptionTest04 {
    public static void main(String[] args) {
        //main方法中调用 dosome()方法
        //因为 dosome()方法声明位置上有: throws ClassNotFoundException
        //我们在调用Some()方法的时候必须对这种异常进行预先的处理。
        //如果不处理,编译器就报错。
        //dosome();
    }
/*
    dosome方法在方法声明的位置上使用了: throws ClassNot FoundException
    这个代码表示 dosome()方法率执行过程中,有可能会出现 LassNotFoundException异常。
    叫做类没找到异常。这个异常值接父类是: Exception,所 ClassNotFoundException属于编译时异常
    throws ClassNotFoundException*/
    public static void dosome() throws ClassNotFoundException{
        System.out.println("do some");
    }

}

六.异常捕捉和上报的联合使用

大佬总结throw和throws

1.文件找得到

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*处理异常的第一种方式:
        在方法声明的位置上使用 throws关键字抛出,谁调用我这个方法,我就抛给谁。
        抛给调用者来处理。
        这种处理异常的态度:上报。
处理异常的第二种方式:
        使用try.. catch语句对异常进行捕捉。
        这个异常不会上报,自己把这个事儿处理了。
        异常抛到此处为止,不再上抛了*/
public class ExceptionTest06 {
/*  一般不建议在main方法上使用throws,因为这个异常如果真正的发生了,一定会抛给JVM。JVM只有终止。
    异常处理机制的作用就是增强程序的健壮性。怎么能做到,异常发生了也不影啊程序的执行。所以
    一般main方法中的异常建认使用try., catch进行捉。main就不要继续上抛了。*/
    public static void main(String[] args) {
        try {
            m1();
            System.out.println("Hello World");
        } catch (IOException e) {
            System.out.println("文件不纯正,可能路径错误,也可能文件被删除");
        }
    }
    public static void m1() throws IOException{
    	System.out.println("m1 begin");
        m2();
        System.out.println("m1 over");
    }

/* throws 后面也可以抛出多个异常,但是后续还要处理那个classNotFoundException
   public static void m2() throws FileNotFoundException,ClassNotFoundException {
        m3();
    }*/
/*
    抛别的不行,抛 ClassCastException说明你还是没有FileNot FoundException进行处理
    private static void m2() throws ClassCastExceptionf
    抛 ileNot FoundException的父对象 EXception,这样是可以的。
    Exception包括 ileNot FoundException*/
    public static void m2() throws FileNotFoundException {
    System.out.println("m2 begin");
    m3();
    System.out.println("m2 over");
}
    public static void m3() throws FileNotFoundException {
/*        编译报错的原因是什么?
         第-:这里调用了一个构造方法: FileInputstream( String name)
        第二:这个构造方法的声明位置上有: throws FileNot FoundException
        第三:通过类的继承结构看到: FileNotFoundException父类是 IOException, IOException的父类是 Exception
        最终得知, FileNot FoundException是编译时异常
        错误原因?编译时异常要求程序员编写程序阶段必须对它进行处理,不处理编译器就报错。
*/
       // new FileInputStream("D:\\IDM\\Video\\app.asar");
       //我们采用第一种处理方式:在方法声明的位置上使用throws继续上抛。
        new FileInputStream("D:\\IDM\\Video\\app.asar");
    System.out.println("如果以上代码异常,这里会执行嘛??不会");
    }
}

m1 begin
m2 begin

m2 over
m1 over
Hello World
main over

2.文件找不到

new FileInputStream("D:\\IDM\\Video\\ap.asar");

如果以上代码异常,这里会执行嘛??不会m1 over m2 over main over都不会执行 马上跳到catch语句块中,所以并不会执行hellow world
m1 begin
m2 begin
文件不纯正,可能路径错误,也可能文件被删除

3.try catch深入

try语句块抛出异常时,其后的代码不会被执行,如果想继续执行剩余代码,可将剩余代码放在finally语句块中
深入try. catch
1、 catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型。
2、 catch可以写多个。建认 catch的时候,精确的一个一个处理。这样有利于程序的调闻。
3、 catch写多个的时候,从上到下,必须遵守从小到大。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ExceptionTest07 {
    public static void main(String[] args) {
        try{
            //创建输入流
            FileInputStream fis=new FileInputStream("D:\\study\\Java\\fuck\\作业.txt");
            //读文件
            fis.read();
        } catch (FileNotFoundException e) {
            System.out.println("文件不存在");
        }catch (IOException e){
            System.out.println("该文件报错了");
        }
    }
}
public class ExceptionTest07 {
    public static void main(String[] args) {
        try{
            //创建输入流
            FileInputStream fis=new FileInputStream("D:\\study\\Java\\fuck\\作业.txt");
            //进行数学运算
            System.out.println(100/0);
       }
        /*
        catch (FileNotFoundException e) {
            System.out.println("文件不存在");
        }catch (IOException e){
            System.out.println("该文件报错了");
        }*/
         //jdk8 新特性
         catch(FileNotFoundException | java.lang.ArithmeticException | NullPointerException e){
             System.out.println("文件不存在?数字异常?空指针异常?");
         }
    }
}

4.异常对象的常用方法

来自jdk1.8开发文档
getMessage
public String getMessage()
返回该错误的详细信息的字符串。 
结果 
这 Throwable实例的详细信息的字符串(可以 null)。
printStackTrace
public void printStackTrace()
打印到标准错误流这个异常和回溯。这种方法打印一个堆栈跟踪,这在错误输出流,是现场 System.err价值 Throwable对象。输出的第一行包含该对象的 toString()方法的结果。剩余的线代表的方法 fillInStackTrace()先前记录的数据。这些信息的格式依赖于实现

如何取得异常对象的具体信息,常用的方法主要有两种:
1.取得异常描述信息:getMessage()
2.取得异常的堆栈信息(比较适合于程序调试阶段):printStackTrace();

 public class ExceptionTest08 {
/*    异常对亲有两个并常重要的方法:
    获取异常简单的描述信息
    String msg exception getMessage()
    打印异常追踪的堆找信息
exception. printstackTrace();*/
    public static void main(String[] args) {
/*      这里只是为了测getMessage()方法和pnintStackTrace()方法。
        这里只是new异常对象,但是没有将异常对抛.JVM会认为这是一个普通的java对象。*/
        NullPointerException e=new NullPointerException("空指针异常");
        //获取异常筒单描述信息:这个信息实际上就是构造方法上面String参数
        String s=e.getMessage();//空指针异常
        System.out.println(s);
/*        打印异常堆找信息
          java后台打印异常堆找追踪信息的时候,采用了异步线程的方式打印
          所以不一定空指针异常还是那个堆栈信息先后出来不一定*/
        e.printStackTrace();
    }
}

空指针异常
java.lang.NullPointerException: 空指针异常
at ExceptionTest06.main(ExceptionTest06.java:10)

实战
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/*异常对象的两个方法
        String msg = e.getMessageO
        e printStackTrace();

        我们以后查看异常的追踪信息,我们应该怎么看,可以快速的调试程序呢?
        异常信息追踪信息,从上往下一行一行看
        但是需要注意的是:SUN写的代码就不用看了(看包名就知道是自己的还是SUN的。)
        主要的问题是出现在自己编写的代码上。*/
public class ExceptionTest09 {
    public static void main(String[] args) {
        try {
            m1();
        } catch (FileNotFoundException e) {
            //获取异常简单描述信息
            String msg=e.getMessage();
            System.out.println(msg);
            //打印异常堆找追踪信息!!!
            //在实际的开发中,建议使用这个。养成好习惯
            e.printStackTrace();
/*            java.io.FileNotFoundException: D:\Tencent\QQLicense.tf (系统找不到指定的文件。)
            at java.base/java.io.FileInputStream.open0(Native Method)
            at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
            at java.base/java.io.FileInputStream.<init>(FileInputStream.java:155)
            at java.base/java.io.FileInputStream.<init>(FileInputStream.java:110)
            at com.Exception.ExceptionTest09.m3(ExceptionTest09.java:21)
            at com.Exception.ExceptionTest09.m2(ExceptionTest09.java:18)
            at com.Exception.ExceptionTest09.m1(ExceptionTest09.java:15)
            at com.Exception.ExceptionTest09.main(ExceptionTest09.java:9)

            */
        }
        //这里程序不耽误执行,很健壮(服务器不会遭到异常而宕机)
        System.out.println("Hello World");
    }
    public static void m1() throws FileNotFoundException {
        m2();
    }
    public static void m2() throws FileNotFoundException {
        m3();
    }
    public static void m3() throws FileNotFoundException {
        new FileInputStream("D:\\Tencent\\QQicense.rtf");
    }

}

“C:\Program Files\Java\jdk-13.0.2\bin\java.exe” “-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2020.2\lib\idea_rt.jar=3418:C:\Program Files\JetBrains\IntelliJ IDEA 2020.2\bin” -Dfile.encoding=UTF-8 -classpath D:\Study\Javahomework\访问控制权限\out\production\访问控制权限 com.Exception.ExceptionTest09
D:\Tencent\QQicense.rtf (系统找不到指定的文件。)
Hello World
java.io.FileNotFoundException: D:\Tencent\QQicense.rtf (系统找不到指定的文件。)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
at java.base/java.io.FileInputStream.(FileInputStream.java:155)
at java.base/java.io.FileInputStream.(FileInputStream.java:110)
at com.Exception.ExceptionTest09.m3(ExceptionTest09.java:46)
at com.Exception.ExceptionTest09.m2(ExceptionTest09.java:43)
at com.Exception.ExceptionTest09.m1(ExceptionTest09.java:40)
at com.Exception.ExceptionTest09.main(ExceptionTest09.java:16)

Process finished with exit code 0

7.关于try… catch中的 finally子句

1、在finally子句中的代码是最后执行的,并且是一定会执行的,即使try语句块中的代码出现了异常。finally子句必须和try一起出现,不能单独编写。
2、 finally语句通常使用在娜些情况下呢?
通常在 finally语句块中完成资源的释放/关闭。
因为 finally中的代码比较有保障。
即使try语句块中的代码出现异常, finally中代码也会正常执行。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ExceptionTest10 {
    public static void main(String[] args) {
        FileInputStream fis=null;
        try {
          fis=new FileInputStream("D:\\Tencent\\QQLicense.rtf");
            //这里一定会出空指针异常
            String s=null;
            s.toString();
            System.out.println("Hello World");
/*            /流使用完需要关闭,因为流是占用资源的
              /即使以上程序出现异常,流也必须要关闭!
              /放在这里有可能流关不了。*/
           // fis.close();
        } catch (FileNotFoundException e) {
            //因为上述文件路径有效这里并没有执行
            e.printStackTrace();
        } catch (NullPointerException e){
            e.printStackTrace();
        }finally {
            try {
                System.out.println("in work");
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

java.lang.NullPointerException
at com.Exception.ExceptionTest10.main(ExceptionTest10.java:14)
in work

public class ExceptionTest13 {
    public static void main(String[] args) {
        int i=100;
        int result=m1(i);
        System.out.println(result);
    }
/*    java语法规则(有一些规则是不能破坏的,一且这么说了,就必须这么做!):
    java中有一条这样的规则
    方法体中的代码必须遵循自上而下顺序次逐行执行(亘古不变的语法!)
    java中还有一条语法规则
    return语句一且执行,整个方法必须结束(互古不变的语法!)*/
    //除非在try中写上System.exit(0);退出JVM虚拟机,否则finally中代码一定执行
    //这里是因为创建了j局部变量,使得100
    public static int m1(int i){
       try{
           return i;
       }finally {
           i++;
       }
    }

}
//反编译运行结果
/*public static int m()
{       int i =100;
        int j=i;
        i++;
        return j;
        Exception exception
        exception;
        i++
        throw exception;
}
 */

100

final finally finalize有什么区别?
final关键字
final修饰的类无法继承
final修饰的方法无法覆盖
final修饰的变量不能重新厨值。
finally 关键字
积try-起联合使用。
finally语句块中的代码是必须执行的。
finalize 标识符
是一个0bject类中的方法名。
这个方法是由垃级回收器G C负责调用的。

8.自定义异常

Java中怎么自定义异常呢?
两步:
第一步:编写一个类继承Exception或者 RuntimeException
第二步:提供两个构造方法,一个无参数的,一个带有 String参数的。
死记硬背(sun公司的格式)

public class MyException extends Exception {
    public MyException(){
    
    }
    public MyException(String s){
        super(s);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值