当前位置: 首页 > article >正文

Java 异常一口气讲完!(_ _)。゜zzZ

Java 异常处理

Java面向对象设计 - Java异常处理

异常是在没有定义正常执行路径时在Java程序的执行期间可能出现的条件。

Java通过将执行操作的代码与处理错误的代码分离来处理错误。

当发生异常时,Java会创建一个包含有关异常的所有信息的对象,并将其传递给相应的异常处理代码。

有关异常的信息包括异常的类型,发生异常的代码中的行号等。

try-catch块

要处理异常,请将代码放在try块中。try块如下所示:

try  {
    // Code for the try block
}

try块以关键字try开头,后面是开括号和结束括号。

try块的代码放在开口和关闭大括号内。

try块本身不能使用。

它必须后跟一个或多个catch块,或一个finally块,或两者的组合。

要处理可能在try块中抛出的异常,请使用catch块。

一个catch块可用于处理多种类型的异常。

catch块的语法与方法的语法相似。

catch (ExceptionClassName parameterName)   {
    // Exception handling  code
}

catch块的声明就像一个方法声明。

它从关键字catch开始,后面跟一对括号。

在括号中,它声明了一个参数。

参数类型是应该捕获的异常类的名称。

parameterName是用户给定的名称。括号后面是开口括号和结束括号。异常处理代码放在大括号中。

当抛出异常时,异常对象的引用将复制到parameterName。

我们可以使用parameterName从异常对象中获取信息。

我们可以将一个或多个catch块与try块关联。

try-catch块的一般语法如下。

try  {
    // Your code  that may throw  an  exception
}
catch  (ExceptionClass1 e1){
    // Handle  exception of  ExceptionClass1 type
}
catch  (ExceptionClass2 e2){
    // Handle  exception of  ExceptionClass2 type
}
catch  (ExceptionClass3 e3){
    // Handle  exception of  ExceptionClass3 type
}

例子

下面的代码显示了如何处理除零异常。

public class Main {
  public static void main(String[] args) {
    int x = 10, y = 0, z;
    try {
      z = x / y;
      System.out.println("z = " + z);
    } catch (ArithmeticException e) {
      String msg = e.getMessage();

      System.out.println("The error is: " + msg);
    }

    System.out.println("The end.");
  }
}

上面的代码生成以下结果。

Java 异常类

Java面向对象设计 - Java异常类

异常类层次结构

异常类层次结构从java.lang.Throwable类开始。

当抛出异常时,它必须是Throwable类的对象或其任何子类。

catch块的参数必须是Throwable类型,或其子类之一,例如Exception,ArithmeticException,IOException等。

我们可以通过从一个异常类继承我们的类来创建我们自己的异常类。

使用多个catch块

Java运行时选择适当的catch块,并从第一个catch块开始顺序寻找合适的catch时钟。

try块的多个catch块必须从最具体的异常类型排列为最通用的异常类型。

以下代码使用多个catch块的有效序列。

ArithmeticException类是RuntimeException类的子类。

如果这两个异常都在同一个try块的catch块中处理,那么最具体的类型,即ArithmeticException,必须出现在最通用的类​​型之前,即RuntimeException。

try  {
// Do  something, which  might  throw  Exception
}
catch(ArithmeticException e1)  {
// Handle  ArithmeticException first
}
catch(RuntimeException e2)  {
// Handle  RuntimeException after  ArithmeticException
}

已检查和未检查异常

有三种类型的异常:

  • 有一些例外,有更高的可能发生。我们可以在try-catch块中处理它们。或者我们可以在调用方法/构造函数声明中指定它可能抛出异常。
  • 错误是可能发生的异常,并且我们几乎不能处理它。例如,java.lang.OutOfMemeoryError。我们不能做任何事情从内存不足错误中恢复。
    异常类层次结构中的类,它们是Error类的子类和Error类本身,属于此类别的异常。
    编译器不坚持对我们的代码采取行动。如果在运行时抛出此类异常,运行时将通过显示详细的错误消息并暂停应用程序来处理它。
  • 在运行时可能会发生异常,我们可能会从异常条件中恢复。
    异常类层次结构中的类,它们是RuntimeException类的子类和RuntimeException类本身,属于此类别。
    编译器不坚持对我们的代码采取行动。

第一类中的异常称为检查异常,因为编译器检查它们是否在代码中处理。

Throwable类,Exception类和Exception类的子类(不包括RuntimeException类及其子类)称为检查异常。

所有未检查异常的异常称为未检查异常,因为编译器不检查它们是否在代码中处理。

Error类,Error类的所有子类,RuntimeException类及其所有子类都是未检查的异常。

我们可以处理未检查的异常,如果我们想,编译器不会强迫我们这样做。

用于处理已检查或未检查异常的程序结构是相同的。

以下代码显示如何处理已检查的异常:

import java.io.IOException;

public class Main {
  public static void main(String[] argv) {
    try {
      int input = System.in.read();
      if (input != -1) {
        System.out.println(input);
      }
    } catch (IOException e) {
      System.out.print("IOException occurred.");
    }
  }
}

Java 异常抛出

Java面向对象设计 - Java异常抛出

如果一段代码可能抛出一个已检查的异常,我们有两个选择:

  • 使用try-catch块处理已检查的异常。
  • 在方法/构造函数声明中用throws子句指定。

语法

throws子句的一般语法是

<modifiers> <return type> <method name>(<params>) throws<List of Exceptions>{
    
}

关键字throws用于指定throws子句。

throws子句放在方法参数列表的右括号之后。

throws关键字后面是以逗号分隔的异常类型列表。

例子

下面的代码展示了如何在方法的声明中使用throws子句。

import java.io.IOException;

public class Main {
  public static void readChar() throws IOException {
    int input = System.in.read();
    
  }
}

这里是显示如何使用它的代码。

例2

import java.io.IOException;

public class Main {
  public static void readChar() throws IOException {
    int input = System.in.read();
    System.out.println(input);
  }

  public static void main(String[] args) {
    try {
      readChar();
    } catch (IOException e) {
      System.out.println("Error occurred.");
    }
  }

}

上面的代码生成以下结果。

例3

我们可以继续抛出异常。

import java.io.IOException;

public class Main {
  public static void readChar() throws IOException {
    int input = System.in.read();
    System.out.println(input);
  }

  public static void main(String[] args) throws IOException {
    readChar();
  }
}

上面的代码生成以下结果。

抛出异常

我们可以使用throw语句在我们的代码中抛出异常。

throw语法的语法是

throw <A throwable object reference>;

throw是一个关键字,后面是一个对可抛出对象的引用。

throwable对象是一个类的实例,它是Throwable类的子类,或Throwable类本身。

以下是throw语句的示例,它抛出一个IOException:

// Create an  object of  IOException
IOException e1  = new IOException("File not  found");
// Throw the   IOException 
throw  e1;

以下是throw语句的示例,它抛出一个IOException:

// Throw an  IOException
throw  new IOException("File not  found");

如果我们抛出一个被检查的异常,我们必须使用try-catch块来处理它,或者在方法或构造函数声明中使用throws子句。

如果您抛出未经检查的异常,这些规则不适用。

Java 自定义异常

Java面向对象设计 - Java自定义异常

我们可以创建我们自己的异常类。

它们必须扩展现有的异常类。

<Class Modifiers> class <Class Name> extends <Exception Class Name> {
  
}
&lt;Class Name> is the exception class name.

创建一个MyException类,它扩展了java.lang.Exception类。

语法

语法如下:

public class MyException  extends  Exception  {
}

异常类与Java中的任何其他类一样。通常,我们不向我们的异常类中添加任何方法。

许多有用的方法可以用来查询异常对象的状态在Throwable类中声明。

自定义异常类构造函数

通常,我们为我们的异常类包括四个构造函数。

所有构造函数将使用super关键字调用其超类的相应构造函数。

class MyException extends Exception {
  public MyException() {
    super();
  }

  public MyException(String message) {
    super(message);
  }

  public MyException(String message, Throwable cause) {
    super(message, cause);
  }

  public MyException(Throwable cause) {
    super(cause);
  }
}

第一个构造函数创建一个具有null的异常作为其详细消息。

第二个构造函数创建一个具有详细消息的异常。

第三和第四个构造函数允许您通过包装/不包含详细消息的另一个异常来创建异常。

您可以抛出类型MyException的异常。

throw new MyException("Your  message  goes  here");

我们可以在方法/构造函数声明中的throws子句中使用MyException类,或者在catch块中使用参数类型。

public void  m1()  throws   MyException  {
}

或捕获异常类

try  {

}catch(MyException e)  {

}

Throwable

下面的列表显示了Throwable类的一些常用方法。

Throwable类是Java中所有异常类的超类。此表中显示的所有方法在所有异常类中都可用。

  • Throwable getCause()
    返回异常的原因。如果未设置异常的原因,则返回null。
  • String getMessage()
    返回异常的详细消息。
  • StackTraceElement[] getStackTrace()
    返回堆栈跟踪元素的数组。
  • Throwable initCause(Throwable cause)
    设置异常的原因。
    有两种方法可以将异常设置为异常的原因。其他方法是使用构造函数,它接受原因作为参数。
  • void printStackTrace()
    在标准错误流上打印堆栈跟踪。
  • void printStackTrace(PrintStream s)
    将堆栈跟踪打印到指定的PrintStream对象。
  • void printStackTrace(PrintWriter s)
    将堆栈跟踪打印到指定的PrintWriter对象。
  • String toString()
    返回异常对象的简短描述。

例外

以下代码演示了对异常类使用printStackTrace()方法。

public class Main {
  public static void main(String[] args) {
    try {
      m1();
    } catch (MyException e) {
      e.printStackTrace(); // Print the stack trace
    }
  }

  public static void m1() throws MyException {
    m2();
  }

  public static void m2() throws MyException {
    throw new MyException("Some  error has  occurred.");
  }
}
class MyException extends Exception {
  public MyException() {
    super();
  }

  public MyException(String message) {
    super(message);
  }

  public MyException(String message, Throwable cause) {
    super(message, cause);
  }

  public MyException(Throwable cause) {
    super(cause);
  }
}

上面的代码生成以下结果。

例2

以下代码显示了如何将异常的堆栈跟踪写入字符串。

import java.io.PrintWriter;
import java.io.StringWriter;

public class Main {
  public static void main(String[] args) {
    try {
      m1();
    } catch (MyException e) {
      String str = getStackTrace(e);
      System.out.println(str);
    }
  }
  public static void m1() throws MyException {
    m2();
  }

  public static void m2() throws MyException {
    throw new MyException("Some  error has  occurred.");
  }

  public static String getStackTrace(Throwable e) {
    StringWriter strWriter = new StringWriter();
    PrintWriter printWriter = new PrintWriter(strWriter);
    e.printStackTrace(printWriter);

    // Get the stack trace as a string
    String str = strWriter.toString();

    return str;
  }
}

class MyException extends Exception {
  public MyException() {
    super();
  }

  public MyException(String message) {
    super(message);
  }

  public MyException(String message, Throwable cause) {
    super(message, cause);
  }

  public MyException(Throwable cause) {
    super(cause);
  }
}

上面的代码生成以下结果。

Java 终止块 

Java 面向对象设计 - Java 终止块

try ​块也可以有零个或一个​ finally​ 块。 ​finally ​块总是与 ​try ​块一起使用。

语法

使用 ​finally​ 块的语法是

finally  {
    // Code for finally block 
}

finally​ 块以关键字 ​finally​ 开始,后面紧跟一对大括号。

finally​ 块的代码放在大括号内。

try​,​catch​ 和​ finally​ 块有两种可能的组合:​ try - catch - finally ​或​ try - finally ​。

try ​块可以后跟零个或多个​ catch​ 块。

try​ 块最多可以有一个 ​finally​ 块。

try​ 块必须有一个​ catch​ 块,一个 ​finally​ 块,或者两者兼而有之。

try-catch-finally​ 块的语法是:

try  {
    // Code for try block
}
catch(Exception1 e1)  {
    // Code for catch block
}
finally  {
    // Code for finally block
}

try - finally ​块的语法是:

try  {
    // Code for try block
}
finally  {
    // Code for finally block
}

无论在相关联的​ try ​和 ​/​ 或 ​catch​ 块中发生什么,​finally ​块都被保证被执行。

通常,我们使用 ​finally​ 块来写清理代码。

例如,我们可能获得一些资源,当我们完成它们时,必须释放。

try - finally​ 块允许你实现这个逻辑。

您的代码结构将如下所示:

try  {
    // Obtain   and  use  some resources here
}
finally  {
    // Release the   resources that were  obtained in the   try  block
}

例子

下面的代码演示了​ finally ​块的使用。

public class Main {
  public static void main(String[] args) {
    int x = 10, y = 0, z = 0;
    try {
      System.out.println("Before dividing x  by  y.");
      z = x / y;
      System.out.println("After dividing x  by  y.");
    } catch (ArithmeticException e) {
      System.out.println("Inside  catch block a.");
    } finally {
      System.out.println("Inside finally  block a.");
    }

    try {
      System.out.println("Before setting  z  to 2.");
      z = 2;
      System.out.println("After setting  z  to 2.");
    }
    catch (Exception e) {
      System.out.println("Inside  catch block b.");
    } finally {
      System.out.println("Inside finally  block b.");
    }
    try {
      System.out.println("Inside try block c.");
    }
    finally {
      System.out.println("Inside finally  block c.");
    }

    try {
      System.out.println("Before  executing System.exit().");
      System.exit(0);
      System.out.println("After  executing System.exit().");

    } finally {
      // This finally block will not be executed
      // because application exits in try block
      System.out.println("Inside finally  block d.");
    }
  }
}

上面的代码生成以下结果。

重新引用异常

捕获的异常可以重新引用。

public class Main {
  public static void main(String[] args) {
    try {
      m1();
    } catch (MyException e) {
      // Print the stack trace 
      e.printStackTrace();
    }
  }

  public static void m1() throws MyException {
    try {
      m2();
    } catch (MyException e) {
      e.fillInStackTrace();
      throw e;
    }
  }

  public static void m2() throws MyException {
    throw new MyException("An  error has  occurred.");
  }
}

class MyException extends Exception {
  public MyException() {
    super();
  }

  public MyException(String message) {
    super(message);
  }

  public MyException(String message, Throwable cause) {
    super(message, cause);
  }

  public MyException(Throwable cause) {
    super(cause);
  }
}

上面的代码生成以下结果。

Java 异常使用

Java面向对象的设计 - Java异常使用

访问线程的堆栈

以下代码显示了如何获取线程的堆栈帧。

Throwable对象在创建线程的点处捕获线程的堆栈。

public class Main {
  public static void main(String[] args) {
    m1();
  }

  public static void m1() {
    m2();
  }

  public static void m2() {
    m3();
  }
  public static void m3() {
    Throwable t = new Throwable();
    StackTraceElement[] frames = t.getStackTrace();
    printStackDetails(frames);
  }
  public static void printStackDetails(StackTraceElement[] frames) {
    System.out.println("Frame count: " + frames.length);
    for (int i = 0; i < frames.length; i++) {
      int frameIndex = i; // i = 0 means top frame
      System.out.println("Frame Index: " + frameIndex);
      System.out.println("File Name: " + frames[i].getFileName());
      System.out.println("Class Name: " + frames[i].getClassName());
      System.out.println("Method Name: " + frames[i].getMethodName());
      System.out.println("Line Number: " + frames[i].getLineNumber());
    }
  }
}

上面的代码生成以下结果。

try-with-resources块

Java 7添加了一个名为try-with-resources的新结构。

使用Java 7中的新的try-with-resources构造,上面的代码可以写成

try (AnyResource aRes = create the resource...) {
    // Work with the resource here. 
    // The resource will be  closed automatically.
}

当程序退出构造时,try-with-resources构造自动关闭资源。

资源尝试构造可以具有一个或多个catch块和/或finally块。

我们可以在try-with-resources块中指定多个资源。两个资源必须用分号分隔。

最后一个资源不能后跟分号。

以下代码显示了try-with-resources使用一个和多个资源的一些用法:

try (AnyResource  aRes1  = getResource1())  {
    // Use aRes1  here
}

try (AnyResource  aRes1  = getResource1(); AnyResource  aRes2  = getResource2())  {
    // Use aRes1  and  aRes2  here
}

我们在try-with-resources中指定的资源是隐式最终的。

在try-with-resources中的资源必须是java.lang.AutoCloseable类型。

Java 7添加了AutoCloseable接口,它有一个close()方法。

当程序退出try-with-resources块时,将自动调用所有资源的close()方法。

在多个资源的情况下,按照指定资源的相反顺序调用close()方法。

class MyResource implements AutoCloseable {

  public MyResource() {
    System.out.println("Creating MyResource.");
  }
  @Override
  public void close() {

    System.out.println("Closing  MyResource...");
  }
}

public class Main {
  public static void main(String[] args) {
    try (MyResource mr = new MyResource();
        MyResource mr2 = new MyResource()) {

    }
  }
}

上面的代码生成以下结果。

Multi-Catch块

Java 7增加了对多catch块的支持,以便在catch块中处理多种类型的异常。

我们可以在multi-catch块中指定多个异常类型。多个异常由竖线(|)分隔。

捕获三个异常:Exception1,Exception2和Exception3。

try  {
    // May  throw  Exception1, Exception2, or  Exception3
}
catch (Exception1 | Exception2 | Exception3  e)  {
    // Handle  Exception1, Exception2, and  Exception3
}

在multi-catch块中,不允许有通过子类化相关的替代异常。

例如,不允许以下multi-catch块,因为Exception1和Exception2是Throwable的子类:

try  {
    // May  throw  Exception1, Exception2, or  Exception3
}
catch (Exception1 | Exception2 | Throwable    e)  {
    // Handle  Exceptions here
}

http://www.kler.cn/news/331571.html

相关文章:

  • 【SQLite】基础操作
  • 【快速删除 node_modules 】rimraf
  • 深入理解回调函数:指针世界的终极挑战(完)
  • CSS内边距
  • ES索引备份
  • 关于建表字段是否该使用 `NOT NULL` 的问题,你怎么看?
  • ubuntu命令行连接wifi
  • Hive数仓操作(十二)
  • C++ 语言特性13 - 强枚举类型
  • IP 数据包分包组包
  • mit6824-01-MapReduce详解
  • 解决 TypeError: Expected state_dict to be dict-like, got <class ‘*‘>.
  • 在 Ubuntu 下通过 Docker 部署 NAS 服务器
  • 损失函数篇 | YOLOv5 引入Unified-IoU 高质量目标检测IoU损失
  • Vue3项目开发——新闻发布管理系统(九)(完结篇)
  • 项目-坦克大战学习-资源冲突解决
  • 算法 | 鹈鹕算法POA-Transformer-LSTM多变量回归预测
  • redis 5的安装及启动(window)
  • csapp_计算机系统通览
  • 数据校验的总结