Java异常处理机制(完结篇)——再看不懂我找不到女朋友

简介: Java异常处理机制(完结篇)——再看不懂我找不到女朋友

异常处理

异常:

对于计算机程序来说,我们不会保证我们写的程序不会出任何问题,就算程序设计没有逻辑错误,那么你能够保证用户会合法按照自己的意愿去输入数据吗?就算用户相当的配合你,你能够保证你在运行程序时不会出现其他问题吗?比如说网络突然中断,或者是电源中断等。

那么我们就要在设计程序时就要考虑到这些问题,保证当程序运行出错时,有相对应的解决方案,而不是直接将异常直接抛到虚拟机导致程序终止运行。

常出现的异常

  • IndexOutOfException:一般是数组下标越界异常
int[] arr=new int[10];
System.out.println(arr[20]);

  • NullPointException:空指针
String string=null;
string.charAt(0);

  • NumberFormatException:数值类型转换错误
String string="abc";
Integer a=Integer.parseInt(string);

  • ArithmeticException:算术异常
int a=2;
int b=0;
a=a/b;

  • ClassCastException:引用类型转换异常
public class Main {
    public static void main(String[] args) {
        String string="";
        Animal dog=new Dog();
        Cat cat=(Cat)dog;
    }
}
class Animal{
}
class Dog extends Animal{
}
class Cat extends Animal{
}

异常处理机制

方式一:try…catch

try {
      //执行代码
}catch (Exception e){
      //解决方案
}

例如当我们计算1/0时,这是会有算术错误,我们可以捕捉在运算时产生的算术异常

try {
      int a=2/0;
}catch (ArithmeticException e){
      e.printStackTrace();
}

这样在遇到算术异常时,我们的catch语句就会捕捉这个异常,进行解决

  • 可以采用多个catch块去捕捉多个异常
  • 但是要注意,小异常放在上面,大异常放在下面
  • 因为大异常是他们的父类,一但它放在上面,其余的小异常就不会被执行
  • 所以优先处理小异常,这样才会使结构清晰,处理更加明确

当我们在try语句块中执行某条语句产生异常时,在它之后的代码就不会执行,此时会转到执行捕捉到该异常的catch块中执行相应语句

在try语句块中定义的变量为局部变量,在catch语句块中是无法访问的

方式二:多异常捕获

从Java7开始,一个catch块可以捕获多种多样的异常

  • 捕获多种异常时,多种异常类型之间用竖线|隔开
  • 捕获多种异常时,异常变量由隐式的final修饰,不能够对该异常变量重新赋值
try {
  int a=1/0;
}catch (ArithmeticException |IndexOutOfBoundsException e){
    System.out.println("程序产生了算术异常或数组越界异常");
    //e=new Exception();改段代码会报错,因为catch括号里面的变量e被final修饰,不可重新赋值
}catch (Exception e){
    e=new Exception();
}

由于多异常捕捉模式的变量是被final修饰的,所以在catch语句块中是无法给变量重新赋值的

方式三:try…catch…finally

当我们在某些时候,在try语句块中会打开一些文件,或者连接数据库等操作,那么一但我们在try语句块中产生了异常,那么我们之后的代码就不会执行,导致文件和数据库等不能及时正确关闭。

  • Java的垃圾回收机制是不会回收任何物理资源,只会回收堆内存中对象所占用的内存

为了保证可以及时回收try里面打开的物理资源,Java异常处理机制提供了finally语句块,这个语句块是在执行完try和catch语句块后,必须要执行的一个代码块,如果在try或者catch中return语句,也不会影响finally的执行,执行完finally后,再去执行return,如果finally中有return语句,那么try和catch语句块中的return就不会被执行,但是有一点如果在try中的是System.exit(1),就不会去执行finally语句块了,因为这样会导致直接退出虚拟机。

FileWriter file=null;
try{
      file=new FileWriter("text.txt");
}catch (IOException e){
      e.printStackTrace();
}finally {
      if(file!=null){
           try {
                file.close();
           } catch (IOException e) {
                e.printStackTrace();
    }
  }
}

这样一但try块出现异常,该代码依然会执行finally中的close方法将文件关闭

Java7、9增强的自动关闭资源的try语句

当我们在finally中执行关闭资源的代码时,程序显得很臃肿

Java7:
  • Java7增强了try语句的功能,它允许我们在try后面紧跟一对括号,括号里面可以声明定义一些资源
  • 当我们执行完try语句后,程序会自动帮我们关闭资源
  • 这些资源必须实现AutoCloseable接口或者是Closeable接口的close方法
  • Close接口是AutoCloseable的子接口
try (FileWriter file=new FileWriter("text.txt")) {
     file.write("");    
}catch(Exception e){
     e.printStackTrace();
}
Java9:
  • Java9进一步增强该操作,不需要再括号内声明定义了
  • 可以在try语句外面定义
  • 但是该资源变量必须是final或者是有效final就是始终没有被赋过其他值
FileWriter file1=new FileWriter("text.txt");
FileWriter file2=new FileWriter("text.txt");
try(file1;file2){
      file.write("");
}catch(Exception e){
      e.printStackTrace();
}

Checked异常和Runtime异常

对于Java中的异常可分为两大类:

一类是Check异常(编译时异常):

一类是Runtime异常(运行时异常):

所有的RuntimeException类及其子类的异常都是运行时异常,其余是编译时异常

运行时异常是指我们程序在运行后才会出现的异常,这类异常不影响编译,只是在运行过程会发生错误

但是编译时异常,我们必须去显示的处理该异常,否则我们不能通过编译,例如当我们在调用多线程中的sleep方法时,

我们需要用try…catch包住才可以使用,否则就会报错,因为该方法在定义时,抛出了编译异常,需要我们显式处理

使用throws抛出异常

  • 当我们有时不知道如何去处理该异常时,我们就需要将产生的异常对象向上抛
  • 方法会抛给main方法,如果在main方法中没有得到解决,就会继续向上抛
  • 抛给Java虚拟机,打印异常跟踪栈信息,并终止程序运行
  • 这也就是为什么之前我们运行的程序在运行失败后程序会终止,而且在控制台打印一些红色的错误
public static void main(String[] args) throws IOException {
        test();
}
public static void test() throws IOException {
        int a=2/0;
}
public static void main(String[] args){
        try {
            test();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
public static void test() throws IOException {
        int a=2/0;
    }
}

注意:

  • 但我们调用抛出异常的方法时,这个方法要么在try…catch语句块中
  • 要么在另一个带throws的方法中
  • 因为既然方法抛出了异常就要去捕捉进行解决

方法重写时抛异常注意事项

当我们的子类继承父类时,如果父类的方法抛出了异常

子类重写该方法的时候抛出的异常不得大过父类抛出的异常

class A{
    public void test() throws ArithmeticException{
    }
}
class B extends A{
    @Override
    public void test() throws Exception {
    }
}

上述代码会报错,因为子类B抛出的是Exception异常大过父类抛出的异常

使用throw抛出异常

在某些情景下,不一定是真正的异常,只要是不符合我们预期的想法就是异常

当不符合预期时,我们可以手动去抛出异常

public static void main(String[] args){
        int a=-1;
        try {
            if(a<0){
                throw new Exception("a为负数");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

对于Check异常我们要么显式捕捉处理,要么继续抛

而Runnable异常,我们既可以显式捕捉,也可以不予理会

自定义异常类

因为Java定义的异常有限,有时并不会满足我们的需求,这时我们就需要自己去定义一个异常类,实现我们所需要的功能

  • 首先要继承Exception类或者是RuntimeException等基类
  • 然后定义两个构造器
  • 有参构造器通常传入的是错误信息
class MyException extends Exception{
    public MyException(){
    }
    public MyException(String msg){
        super(msg);
    }
}

总结

  • 异常只是应用于处理非正常的情况,不要过度使用异常来代替正常的流程控制
  • 对于一些可预知的错误,程序员完全有能力提供相应代码去处理,而不是去抛异常

例如:

int a[]=new int[10];
for(int i=0;i<100;i++){ 
   try {
       System.out.println(a[i]);
   }catch (IndexOutOfBoundsException e){
       e.printStackTrace();
   }
}
  • 这种情况程序员是可以预料到的,完全有能力利用代码去避免这种错误的发生
    而不是一味的去抛异常再去解决
  • 这种抛异常虽然简单,但是Java运行时捕捉到异常后,还要进入catch块
    这样会降低运行效率
  • 异常处理机制的初衷是将不可预期异常的处理代码和正常的业务逻辑处理代码分离,
    绝不要使用异常处理来代替正常的业务逻辑判断


目录
相关文章
|
5月前
|
Java 编译器
Java中的异常处理机制详解
Java中的异常处理机制详解
|
1月前
|
Java 编译器 数据库连接
Java中的异常处理机制深度解析####
本文深入探讨了Java编程语言中异常处理机制的核心原理、类型及其最佳实践,旨在帮助开发者更好地理解和应用这一关键特性。通过实例分析,揭示了try-catch-finally结构的重要性,以及如何利用自定义异常提升代码的健壮性和可读性。文章还讨论了异常处理在大型项目中的最佳实践,为提高软件质量提供指导。 ####
|
1月前
|
Java 程序员 开发者
Java中的异常处理机制深度解析####
本文将深入浅出地探讨Java编程语言中异常处理的核心概念与实践策略,旨在帮助开发者更好地理解如何构建健壮的应用程序。通过剖析异常体系结构、掌握有效的异常捕获与处理技巧,以及学习最佳实践,读者能够提升代码质量,减少运行时错误,从而增强软件的稳定性和用户体验。 ####
|
4月前
|
Java 数据库连接 UED
java 异常处理机制
java 异常处理机制
34 1
|
5月前
|
监控 Java 程序员
深入理解Java中的异常处理机制
【7月更文挑战第30天】在Java的世界里,异常处理如同一位细心的守门人,时刻监控着程序的运行状态。本文将带领读者走进Java异常处理的大门,探索其设计哲学、分类体系以及最佳实践。我们将从异常的基本概念出发,逐步深入到异常类的层次结构,最后通过实际案例分析,揭示如何优雅地处理异常,确保程序的健壮性和可靠性。
53 2
|
5月前
|
Java 开发者 设计模式
深入理解Java中的异常处理机制
在Java编程世界中,异常处理是代码健壮性的守护神。本文将通过一个独特的视角——将异常处理比作一场戏剧演出,带你深入了解Java的异常处理机制。我们将探索不同类型的异常角色、它们如何登台表演以及我们作为导演(开发者)该如何指导这场戏。准备好,让我们揭开Java异常处理的帷幕,一探究竟。
|
5月前
|
Java 开发者 UED
深入理解Java中的异常处理机制
【7月更文挑战第24天】在Java的世界中,异常处理是维护程序健壮性的关键。本文将探索Java异常处理的核心概念,从基本语法到高级技巧,揭示如何优雅地管理运行时错误。我们将通过实际代码示例,展示捕获、声明和自定义异常的策略,并探讨如何在多线程环境下有效处理异常。
|
5月前
|
Java
Java中的异常处理机制深度解析
本文旨在深入探讨Java语言中异常处理的机制,从基础概念到高级应用,全面剖析try-catch-finally语句、自定义异常以及异常链追踪等核心内容。通过实例演示和代码分析,揭示异常处理在Java程序设计中的重要性和应用技巧,帮助读者构建更为健壮和易于维护的程序。
|
5月前
|
Java 数据库连接 开发者
Java中的异常处理机制与最佳实践
本文旨在深入探讨Java的异常处理机制,揭示异常处理在程序设计中的重要性及其对软件质量的影响。文章将通过案例分析,阐释异常处理的最佳实践,包括自定义异常类的创建、异常链的使用以及如何避免常见的异常处理陷阱。此外,还将讨论如何利用现代Java版本的特性来优化异常处理策略,提升代码的健壮性和可读性。
|
5月前
|
Java 编译器
Java中的异常处理机制详解
Java中的异常处理机制详解