Java中的异常

本文详细介绍了Java中的异常处理机制,包括运行时异常如空指针异常、算术异常等的处理,以及编译时异常如SQLException和IOException的处理。重点讲解了try-catch-finally结构及其在实际编程中的应用和throw与throws关键字的区别。
摘要由CSDN通过智能技术生成

在学习其他语言的时候,我会常忽略异常,但是真的面对自己的项目时,又异常是一个非常有用的存在,所以今天说说Java异常(结合多个up主内容总结)

一、异常的介绍

  1. 将程序执行中发生的不正常情况称为“异常”(程序逻辑错误或者语法的错误不叫异常),例如空指针访问,试图读取不存在的文件,网络连接中断等等
  2. 基本异常类型Throwable:所有错误和异常的超类;
    Error:表示编译时和系统错误(外部错误)。如OutOfMemoryError、StackOverflowError等。这些错误通常是严重的,应用程序不应该尝试捕获。
    Exception:表示需要应用程序来捕获的条件。进一步异常分为2大类:运行时异常和编译时异常
    在这里插入图片描述

二、运行时异常和编译时异常

下面简要的介绍一下运行时异常和编译时异常几个常会遇到的种类

运行时异常:算数异常(ArithmeticException)

解释:
算术异常在Java中是通过ArithmeticException类表示的,它是RuntimeException的一个子类。这意味着ArithmeticException是一个运行时异常,Java编译器不要求程序员显式地处理(即捕获或声明抛出)这种类型的异常。最常见的就是除以零。
例如:

package exception;
public class Exception_Introduction {
    public static void main(String[] args) {
        int n1=100;
        int n2=0;
		int temp=n1/n2;
		System.out.println("除数不能为0");
    }
}

运行时异常:空指针异常(NullPointerException)

解释:
空指针异常(NullPointerException)在Java中是一种运行时异常(RuntimeException的子类),它发生在尝试使用null值调用对象实例方法或访问对象的属性时。因为null表示没有任何对象引用,所以尝试执行任何操作都会导致NullPointerException
例如:

package exception;
public class NullPointerException_ {
    public static void main(String[] args) {
        String name= null;
        System.out.println(name.length);
    }
}

运行时异常:数组索引越界异常(ArrayIndexOutOfBoundsException)

解释:
数组索引越界异常在Java中通过ArrayIndexOutOfBoundsException类表示,它是RuntimeException的一个子类。这种异常发生在尝试访问数组的一个不存在的索引时,即索引值小于0或大于等于数组的长度。
例如:

package exception;
public class ArrayIndexOutOfBoundsException_ {
    public static void main(String[] args) {
        int[] arr={1,2,3,4,5};
        for (int i=0;i<=arr.length;i++){
            System.out.println(arr[i]);
        }
    }
}

运行时异常:数字格式不正确异常(NumberFormatException)

解释:
NumberFormatException是Java中的一个运行时异常(RuntimeException的子类),它发生在尝试将字符串转换为数字格式,但字符串的格式不适合转换为数字时。这种异常通常是由Integer.parseInt()Double.parseDouble()等包装类的解析方法抛出的
例如:

package exception;
public class NumberFormatException_ {
    public static void main(String[] args) {
        String name="Tom";
        int num=Integer.parseInt(name);
        System.out.println(num);
    }

}

编译时异常

解释:
在编译期间,就必须处理的异常,否则代码不能通过编译
常见的编译异常:
1、SQLException:操作数据库时,查询表可能发生的异常
2、IOException:操作文件时发生的异常
3、FileNotFoundException:当操作一个不存在的文件时,发生的异常
4、ClassNotFoundException:加载类,而该类不存在时,发生异常
5、EOFException:操作文件,到文件末尾,发生异常
6、IllegalArguementException:参数异常
例如:

package exception;
import java.io.FileInputStream;
import java.io.IOException;
public class FileNotFoundException_ {
    public static void main(String[] args) {
    //IOException 当操作一个不存在的文件时,发生的异常
          FileInputStream file;
          file = new FileInputStream("./niha.s");
          int len;
          while((len=file.read())!=-1){
              System.out.println(len);
          }
          file.close();
    }
}

三、异常处理机制

解释:

  • 为啥要有异常处理机制?之前我很不理解,我都已经知道这个代码有问题,用if-else就可以将问题排除外呀,还要用异常处理机制吗?很早之前当我有一次用python写一个关于连接串口程序时,我才知道异常处理机制真的很有用,因为无论程序出现异常与否,都需要关闭串口,其中的try-except-finally发挥了重要作用。
  • 继续拿之间的代码举例(如下),程序执行到int temp=n1/n2;时,就会抛出异常(ArithmeticException)后面的代码就不会执行,但是当想执行后面语句时,就需要使用异常处理机制来解决该问题
  • 处理方式(IDEA快捷键):
    电脑快捷键 command+option+t,就会跳出选择框,选择try-catch
    win电脑快捷键 ctrl+alt+t,就会跳出选择框,选择try-catch
package exception;

public class Exception_Introduction {
    public static void main(String[] args) {
        int n1=100;
        int n2=0;
        try {
            //运行时异常
            int temp=n1/n2;
        } catch (Exception e) {
            // throw new RuntimeException(e);
            System.out.println("除数不能为0");
        }
        System.out.println("程序运行");
    }
}

基本介绍:

  1. 异常处理就是当异常发生时,对异常处理的方式
  2. 异常处理的方式:
    try-catch-fially: 捕获代码异常,自行处理
    throws:将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM

try-catch-fially

用法:

try{
可能有异常的代码
}catch(Exception e){
捕获异常
当异常发生时,系统将异常封装成Exception对象e,传递给catch
得到异常对象后,可以自行处理,另外如果没有发生异常,catch就不会执行
可以有多个catch语句,捕获不同的异常(进行不同业务处理,类似与if-else语句),要求父类异常在后。
}finally{
没有finally,语法也是没有问题的
如果有finally,不管try代码块是否有异常发生,始终要执行finally
所以一般情况下将释放资源的代码,放在finally
另外也可以只写try- finally配合使用,这种用法相当于没有捕获异常,程序执行完finally代码块之后还是会崩溃。
}

例如

/*
程序异常
*/
package exception;
public class TryCatch_ {
    public static void main(String[] args) {
        try {
            String str="Tom";
            int num=Integer.parseInt(str);
            System.out.println(num);
        } catch (NumberFormatException e) {
            System.out.println("异常信息:"+e);
        }finally {
            System.out.println("程序还是会继续");
        }
    }
}

输出结果:

异常信息:java.lang.NumberFormatException: For input string: "Tom"
程序还是会继续
/*
程序正常
*/
package exception;
public class TryCatch_ {
    public static void main(String[] args) {
        try {
            String str="231";
            int num=Integer.parseInt(str);
            System.out.println(num);
        } catch (NumberFormatException e) {
            System.out.println("异常信息:"+e);
        }finally {
            System.out.println("程序还是会继续");
        }
    }
}

输出结果:

231
程序还是会继续
package exception;
public class TryCatchFinally_01 {
    public static void main(String[] args) {
        try {
            Person person = new Person();
            person = null;
            // NullPointerException
            System.out.println(person.getName());
            int num1 = 10;
            int num2 = 0;
            // ArithmeticException
            int temp = num1 / num2;
        }catch (ArithmeticException e){
                System.out.println("Exception:"+e);
        } catch (NullPointerException e) {
            System.out.println("Exception:"+e);
        } catch (Exception e){
            System.out.println("Exception:"+e);
        }finally {
        }
    }
}

class Person{
    private String name;
    public String getName(){
        return name;
    }
}

输出结果:

Exception:java.lang.NullPointerException
package exception;
public class TryCatchFinally_02 {
    public static void main(String[] args) {
        try {
            int num1=100;
            int num2=0;
            int temp=num1/num2;
            System.out.println(temp);
        } finally {
            System.out.println("finally代码块执行");
        }
        System.out.println("继续执行");
    }
}

输出结果:

finally代码块执行
Exception in thread "main" java.lang.ArithmeticException: / by zero 
 		at exception.TryCatchFinally_02.main(TryCatchFinally_02.java:9)

下面是一个较难的例子:

package exception;
public class TryCatchFinally_05 {
    public static void main(String[] args) {
        Exercise_03 exercise03 = new Exercise_03();
        int num=exercise03.method();
        System.out.println(num);
    }
}
class Exercise_03{
    private static int i=1;
    public static int method(){
        try {
            i++;
            String[] names =new String[3];
            if (names[1].equals("Tom")){
                System.out.println(names[1]);
            }else {
                names[3]="sxp";
            }
            return 1;
        } catch (ArrayIndexOutOfBoundsException e) {
            return 2;
        } catch (NullPointerException e){
            return ++i;   //保存临时变量temp=3
        }finally { //finally肯定会执行
            ++i;
            System.out.println("i="+i);
        }
    }
}

输出结果:

i=4
3

throws

throws单词就有抛的意思,如果一个方法在执行过程中,可能生成某个异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常处理,而是由方法的调用者处理。在方法声明中用throws语句,可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。

解释:
1、使用throws,抛出异常,让调用方法的调用者处理
2、throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类
3、 throws关键字后也可以是异常列表,可以抛出多个异常

package exception;

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

public class Throws_01 {
    public static void main(String[] args) {
    }
    //下面也可以写成 public void func1() throws Exception
    // 创建一个文件流对象
    // 异常处理,这里是一个FileNotFoundException,编译异常
    // 可以使用 try-catch-finally
    // 也可以使用throws,抛出异常,让调用func1方法的调用者处理
    public static void func1() throws FileNotFoundException,NullPointerException{
        FileInputStream file = new FileInputStream("./dir/test.txt");
    }
}

解释:
1、对于编译异常,程序中必须处理,比如用try-catch或者throws
2、对于运行异常。程序中如果没有处理,默认就是throws的方式处理
3、子类重写父类的方法时,对抛出异常的规定:子类重写方法,所抛出的异常类型要么和父类一致,要么为父类抛出的异常的类型的子类型,否则语法不能通过
例如:

package exception;

public class Throws_02 {
    public static void main(String[] args) {
        func2();
    }
    public static void func2() /*throws ArithmeticException*/{
        // 则该方法相当于public void func2 throw ArithmeticException
        int num1=1000;
        int num2=0;
        int temp=num1/num2;

    }
}
class Father{
    public void method() throws RuntimeException{

    }
}
class Son extends Father{
    @Override
    public void method() throws NullPointerException {

    }
}

解释:
java中不要求在程序中显示的处理运行异常,因为有默认的处理机制
例如:

package exception;

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

public class Throws_03 {
    public static void main(String[] args) {
        func3();
    }
    public static void func3() /*throws ArithmeticException*/{
        // 则该方法相当于public void func2 throw ArithmeticException
        int num1=1000;
        int num2=0;
        int temp=num1/num2;

    }
    // func5方法抛出了一个编译异常
    // 这就要求func4方法处理这种异常
    // 在func4中要么try-catch-finally或者继续使用throws抛出异常
    public static void func4() /* throws Exception */{
        //这里直接调用func6方法不会出现语法问题,因为是func6方法抛出的是运行异常
        //而java中不要求在程序中显示的处理,因为有默认的处理机制
        func6();
        try {
            func5();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            System.out.println("继续执行");
        }
    }
    public static void func5() throws FileNotFoundException {
        FileInputStream file = new FileInputStream("./dir/test.txt");
    }
    public static void func6() throws ArithmeticException{

    }
}

自定义异常

  • 定义类:自定义异常类继承Exception或者RuntimeException
  • 如果继承Exception,属于编译异常
  • 如果继承RuntimeException,属于运行异常
  • 一般来说,自定义异常是继承RuntimeException,把自定义异常做成运行时异常,好处是我们可以使用默认的处理机制
    例如:
package exception;
public class CustomException_01 {
    public static void main(String[] args) {
        int age=10;
        //要求范围在18-120之间,否则抛出一个自定义异常
        if (!(age>=18 && age<=120)){
            throw new AgeException("年龄需要在18~120之间");
        }
        System.out.println("你的年龄是正确的");
    }
}
//自定义异常
class AgeException extends RuntimeException{
    public AgeException(String message){
        super(message);
    }
}

throw和throws的区别

两者意义位置后面跟的内容
throws异常处理的一种方式方法声明处异常类型
throw手动生成异常对象的关键字方法体中异常对象
下面是一个较难的例子:
package exception;
public class ThrowException_02 {
    public static void main(String[] args) {
        try {
            ReturnExceptionDemo.method_1();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        ReturnExceptionDemo.method_2();
    }
}
class ReturnExceptionDemo{
    static void method_1(){
        try {
            System.out.println("进入方法 1");
            throw new RuntimeException("运行时异常");
        } finally {
            System.out.println("方法 1 finally 仍然执行");
        }
    }
    static void method_2(){
        try {
            System.out.println("进入方法 2");
            return ;
        } finally {
            System.out.println("方法 2 finally 仍然执行");
        }
    }
}

输出结果:

进入方法 1
方法 1 finally 仍然执行
运行时异常
进入方法 2
方法 2 finally 仍然执行
  • 55
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java异常机制是一种用于处理程序执行期间可能出现的错误情况的机制。Java异常分为两类:受检异常(Checked Exception)和非受检异常(Unchecked Exception)。其,受检异常必须在代码进行捕获和处理,否则编译器将会报错。而非受检异常则不需要在代码进行捕获和处理,但是如果不进行处理,会导致程序的异常终止。 Java异常机制通过抛出异常对象来表示程序出现的异常情况,通常情况下,异常对象包含了异常的类型、异常的消息以及异常发生的位置等信息。当程序执行过程出现异常情况时,就会抛出相应的异常对象,这个异常对象会被传递给调用栈上的上层方法,直到被捕获或者到达程序的顶层方法。 Java异常机制主要由三个关键字来实现:try、catch和finally。try块包含可能抛出异常的代码,catch块用于捕获并处理异常,finally块则用于执行一些必须要完成的代码,无论是否抛出异常都会执行。 下面是一个简单的Java异常处理的例子: ``` public class ExceptionDemo { public static void main(String[] args) { try { int num = Integer.parseInt(args[0]); System.out.println("10 / " + num + " = " + (10 / num)); } catch (ArithmeticException e) { System.out.println("除数不能为0"); } catch (NumberFormatException e) { System.out.println("请输入数字"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("请至少输入一个参数"); } finally { System.out.println("程序执行完毕"); } } } ``` 在这个例子,我们使用了try-catch-finally关键字来处理用户输入的参数,当输入参数不满足条件时,就会抛出相应的异常。catch块用于捕获并处理异常,finally块则用于执行一些必须要完成的代码,无论是否抛出异常都会执行。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值