Java新手零基础教程!Java 异常详解.^◡^.

Java 异常

Java教程 - Java异常

异常是在运行时在代码序列中出现的异常状况。例如,读取一个不存在的文件。

Java异常是描述异常条件的对象发生在一段代码中。

关键词

Java异常处理通过五个关键字管理: try,catch,throw,throws和finally。

try block包含要监视的程序语句异常。

如果在块中发生异常,则抛出异常。

catch 语句可以捕获异常并以合理的方式处理它。

要手动抛出异常,请使用关键字throw。

任何抛出的异常一个方法必须由一个 throws 子句指定。

任何代码绝对必须是在try块完成之后执行的命令被放在 finally 块中。

语法

要处理一个异常,我们把可能有的代码在try ... catch语句中的异常。

try { 
// block of code to monitor for errors 
} 
catch (ExceptionType1 exOb) { 
// exception handler for ExceptionType1 
}
catch (ExceptionType2 exOb) { 
// exception handler for ExceptionType2 
}

可能有异常的程序语句包含在 try 块中。异常处理程序使用 catch 语句进行编码。

这里, ExceptionType 是发生的异常的类型。

例子

在try块和catch子句中封装要监视的代码。

下面的程序包括一个try块和一个catch子句处理由除法生成的ArithmeticException错误:

public class Main {
  public static void main(String args[]) {
    int d, a;
    try { // monitor a block of code.
      d = 0;
      a = 42 / d;
      System.out.println("This will not be printed.");
    } catch (ArithmeticException e) { // catch divide-by-zero error
      System.out.println("Division by zero.");
    }
    System.out.println("After catch statement.");
  }
}

此程序生成以下输出:

例2

一旦抛出异常,程序控制就会从try块转移到catch块中。执行从未从catch返回到try块。

以下代码处理异常并继续。

import java.util.Random;

public class Main {
  public static void main(String args[]) {
    int a = 0, b = 0, c = 0;
    Random r = new Random();
    for (int i = 0; i < 32000; i++) {
      try {
        b = r.nextInt();
        c = r.nextInt();
        a = 12345 / (b / c);
      } catch (ArithmeticException e) {
        System.out.println("Division by zero.");
        a = 0; // set a to zero and continue
      }
      System.out.println("a: " + a);
    }
  }
}

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

Java 异常语句 

Java教程 - Java异常语句

为了防止和处理运行时错误,请将代码包含在try块中进行监视。

紧跟在try块之后,包括一个catch子句它指定您希望捕获的异常类型。

Java try catch语句

public class Main {
  public static void main(String args[]) {
    try { // monitor a block of code.
      int d = 0;
      int a = 42 / d;
      System.out.println("This will not be printed.");
    } catch (ArithmeticException e) { // catch divide-by-zero error
      System.out.println("Division by zero.");
    }
    System.out.println("After catch statement.");
  }
}

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

多个catch子句

您可以指定两个或多个catch子句,每个捕获不同类型的异常。

当抛出异常时,将按顺序检查每个catch语句,并执行类型与异常类型匹配的第一个。

在执行一个catch语句之后,绕过其他catch语句,并在try/catch块之后继续执行。

public class Main {
  public static void main(String args[]) {
    try {
      int a = args.length;
      System.out.println("a = " + a);
      int b = 42 / a;
      int c[] = { 1 };
      c[42] = 99;
    } catch (ArithmeticException e) {
      System.out.println("Divide by 0: " + e);
    } catch (ArrayIndexOutOfBoundsException e) {
      System.out.println("Array index oob: " + e);
    }
    System.out.println("After try/catch blocks.");
  }
}

当您使用多个catch语句时,异常子类必须在它们的任何超类之前。

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

嵌套try语句

try语句可以嵌套。

public class Main {
  public static void main(String args[]) {
    try {
      int a = args.length;
      int b = 42 / a;
      System.out.println("a = " + a);
      try { // nested try block
        if (a == 1)
          a = a / (a - a); // division by zero exception
        if (a == 2) {
          int c[] = { 1 };
          c[4] = 9; // an out-of-bounds exception
        }
      } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Array index out-of-bounds: " + e);
      }
    } catch (ArithmeticException e) {
      System.out.println("Divide by 0: " + e);
    }
  }
}

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

Java throw语句

我们可以在异常情况下抛出异常。

语法

throw的一般形式如下所示:

 throw ThrowableInstance; 

这里,ThrowableInstance必须是Throwable类型的对象或Throwable的子类。

有两种方法可以获取Throwable对象:在catch子句中使用参数,或者使用new运算符创建一个。

执行流程在throw语句之后立即停止; 任何后续不执行语句。

如何使用Java throws语句?

public class Main {
  static void aMethod() {
    try {
      throw new NullPointerException("demo");
    } catch (NullPointerException e) {
      System.out.println("Caught inside demoproc.");
      throw e; // rethrow the exception
    }
  }

  public static void main(String args[]) {
    try {
      aMethod();
    } catch (NullPointerException e) {
      System.out.println("Recaught: " + e);
    }
  }
}

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

Java throws语句

如果一个方法想抛出一个异常,它必须指定这个行为。

这是包含throws子句的方法声明的一般形式:

type method-name(parameter-list) throws exception-list 
{ 
// body of method 
}

exception-list是一个逗号分隔的列表,列出了方法可以抛出的异常。

public class Main {
  static void throwOne() throws IllegalAccessException {
    System.out.println("Inside throwOne.");
    throw new IllegalAccessException("demo");
  }

  public static void main(String args[]) {
    try {
      throwOne();
    } catch (IllegalAccessException e) {
      System.out.println("Caught " + e);
    }
  }
}

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

Java finally语句

任何代码,将被执行,不管try块放在一个 finally 阻止。

这是异常处理块的一般形式:

try { 
// block of code to monitor for errors 
} 
catch (ExceptionType1 exOb) { 
// exception handler for ExceptionType1 
}
catch (ExceptionType2 exOb) { 
// exception handler for ExceptionType2 
}
// ... 
finally { 
// block of code to be executed after try block ends 
}

finally 创建一个代码块在 try/catch 块完成后执行。

即使没有catch语句与异常匹配, finally 块也将执行。

finally 块可用于关闭文件句柄和释放任何其他资源。finally子句是可选的。

public class Main {
  // Through an exception out of the method.
  static void methodC() {
    try {
      System.out.println("inside methodC");
      throw new RuntimeException("demo");
    } finally {
      System.out.println("methodC finally");
    }
  }

  // Return from within a try block.
  static void methodB() {
    try {
      System.out.println("inside methodB");
      return;
    } finally {
      System.out.println("methodB finally");
    }
  }

  // Execute a try block normally.
  static void methodA() {
    try {
      System.out.println("inside methodA");
    } finally {
      System.out.println("methodA finally");
    }
  }

  public static void main(String args[]) {
    try {
      methodC();
    } catch (Exception e) {
      System.out.println("Exception caught");
    }
    methodB();
    methodA();
  }
}

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

Java 异常类型 

Java教程 - Java异常类型

下图显示了Java异常类型层次结构:

Throwable
 |
 |
 +---Exception. 
 |    |
 |    |
 |    +--- RuntimeException
 |
 +---Error

异常及其子类用于用户程序应捕获的异常条件。您可以子类化Exception以创建自己的自定义异常类型。

错误定义在正常情况下不期望捕获的异常。 Java运行时系统使用错误以指示运行时环境中的错误。 堆栈溢出是这种错误的一个例子。

未捕获异常

这个小程序包括一个有意造成除以零误差的表达式:

public class Main {
  public static void main(String args[]) {
    int d = 0;
    int a = 42 / d;
  }
}

以下是执行此示例时生成的异常:

例子

这里是另一个版本的前面的程序,引入相同的错误,但在一个方法与main()分开:

public class Main {
  static void subroutine() {
    int d = 0;
    int a = 10 / d;
  }

  public static void main(String args[]) {
    subroutine();
  }
}

从默认异常处理程序生成的堆栈跟踪显示如何显示整个调用堆栈:

例2

您可以在println()语句中显示异常描述消息。

例如,catch块可以这样写:

import java.util.Random;

public class Main {
  public static void main(String args[]) {
    int a = 0, b = 0, c = 0;
    Random r = new Random();
    for (int i = 0; i < 32000; i++) {
      try {
        b = r.nextInt();
        c = r.nextInt();
        a = 12345 / (b / c);
      } catch (ArithmeticException e) {
        System.out.println("Exception: " + e); 
        a = 0; // set a to zero and continue
      }
      System.out.println("a: " + a);
    }
  }
}

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

什么是Java的内置异常

子类化RuntimeException的异常不需要包含在任何方法的throws列表中。这些被称为未检查异常。

java.lang中定义的未检查异常在下表中列出。

异常含义
ArithmeticException算术错误,如除以零。
ArrayIndexOutOfBoundsException数组索引超出边界。
ArrayStoreException分配给不兼容类型的数组元素。
ClassCastException投射无效。
EnumConstantNotPresentException尝试使用未定义的枚举值。
IllegalArgumentException用于调用方法的非法参数。
IllegalMonitorStateException非法监视器操作,例如等待解锁的线程。
IllegalStateException环境或应用程序状态不正确。
IllegalThreadStateException请求的操作与当前线程状态不兼容。
IndexOutOfBoundsException一些类型的索引是超出界限的。
NegativeArraySizeException使用负尺寸创建的数组。
NullPointerException无效引用的使用无效。
NumberFormatException字符串到数字格式的转换无效。
SecurityException试图违反安全。
StringIndexOutOfBounds尝试在字符串的边界之外建立索引。
TypeNotPresentException未找到类型。
UnsupportedOperationException遇到不支持的操作。

检查的异常在下表中列出。

异常含义
ClassNotFoundException找不到类。
CloneNotSupportedException尝试克隆不实现Cloneable接口的对象。
IllegalAccessException对类的访问被拒绝。
InstantiationException尝试创建抽象类或接口的对象。
InterruptedException一个线程已被另一个线程中断。
NoSuchFieldException请求的字段不存在。
NoSuchMethodException请求的方法不存在。

Java自定义异常类

您可以通过定义 Exception 的子类来创建自己的异常类。

异常类没有定义自己的任何方法。它继承由 Throwable 提供的方法。

以下程序创建自定义异常类型。

class MyException extends Exception {
  private int detail;

  MyException(int a) {
    detail = a;
  }

  public String toString() {
    return "MyException[" + detail + "]";
  }
}

public class Main {
  static void compute(int a) throws MyException {
    System.out.println("Called compute(" + a + ")");
    if (a > 10)
      throw new MyException(a);
    System.out.println("Normal exit");
  }

  public static void main(String args[]) {
    try {
      compute(1);
      compute(20);
    } catch (MyException e) {
      System.out.println("Caught " + e);
    }
  }
}

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

Java链接异常

链接异常允许您将另一个异常与异常相关联。第二个异常描述了第一个异常的原因。

为了允许链接异常,两个构造函数和两个方法被添加到 Throwable 

Throwable(Throwable causeExc) 
Throwable(String msg, Throwable causeExc)

这里是一个例子,说明处理链接异常的机制:

public class Main {
  static void demoproc() {
    NullPointerException e = new NullPointerException("top layer");
    e.initCause(new ArithmeticException("cause"));
    throw e;
  }

  public static void main(String args[]) {
    try {
      demoproc();
    } catch (NullPointerException e) {
      System.out.println("Caught: " + e);
      System.out.println("Original cause: " + e.getCause());
    }
  }
}

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

  • 17
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值