Common Java Exceptions – 常见的Java例外情况

最后修改: 2018年 7月 19日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

This tutorial focuses on some common Java exceptions.

本教程重点介绍一些常见的Java异常。

We’ll start by discussing what an exception basically is. Later, we’ll discuss different types of checked and unchecked exceptions in detail.

我们先讨论一下异常基本上是什么。稍后,我们将详细讨论不同类型的有检查和无检查的异常。

2. Exceptions

2.例外情况

An exception is an abnormal condition that occurs in a code sequence during the execution of a program. This abnormal condition arises when a program violates certain constraints at runtime.

异常是指在程序执行过程中,在代码序列中出现的异常情况。当程序在运行时违反了某些约束条件时,就会出现这种异常情况。

All exception types are subclasses of the class Exception. This class is then subclassed into checked exceptions and unchecked exceptions. We’ll consider them in detail in the subsequent sections.

所有的异常类型都是Exception类的子类。这个类又被子类化为检查性异常和非检查性异常。我们将在后面的章节中详细考虑它们。

3. Checked Exceptions

3.检查过的异常情况

Checked exceptions are mandatory to handle. They are direct subclasses of the class Exception.

检查的异常是必须处理的。它们是Exception类的直接子类。

There’s a debate on their importance that’s worth taking a look.

有一个关于其重要性的争论,值得一看。

Let’s define some checked exceptions in detail.

让我们来详细定义一些被检查的例外情况。

3.1. IOException

3.1.IOException

A method throws an IOException or a direct subclass of it when any Input/Output operation fails. 

当任何输入/输出操作失败时,一个方法会抛出一个IOException或其直接子类。

Typical uses of these I/O operations include:

这些I/O操作的典型用途包括。

  • Working with the file system or data streams using java.io package
  • Creating network applications using java.net package

FileNotFoundException

FileNotFoundException

FileNotFoundException is a common type of IOException while working with the file system:

FileNotFoundException是在使用文件系统时常见的IOException类型。

try {
    new FileReader(new File("/invalid/file/location"));
} catch (FileNotFoundException e) {
    LOGGER.info("FileNotFoundException caught!");
}

MalformedURLException

MalformedURLException

When working with URLs, we might encounter with MalformedURLException – if our URLs are invalid.

在处理URL时,如果我们的URL无效,我们可能会遇到MalformedURLException –

try {
    new URL("malformedurl");
} catch (MalformedURLException e) {
    LOGGER.error("MalformedURLException caught!");
}

3.2. ParseException

3.2.ParseException

Java uses text parsing to create an object based on a given String. If parsing causes an error, it throws a ParseException.

Java使用文本解析来根据给定的String创建一个对象。 如果解析导致错误,它会抛出一个ParseException

For instance, we could represent Date in different ways e.g. dd/mm/yyyy or dd,mm,yyyy, but try to parse a string with a different format:

例如,我们可以用不同的方式表示Date,例如dd/mm/yyyydd,mm,yyyy,,但是尝试解析一个具有不同格式的string

try {
    new SimpleDateFormat("MM, dd, yyyy").parse("invalid-date");
} catch (ParseException e) {
    LOGGER.error("ParseException caught!");
}

Here, the String is malformed and causes a ParseException.

这里,String是畸形的,并导致ParseException

3.3. InterruptedException

3.3.InterruptedException

Whenever a Java thread calls join(), sleep() or wait() it goes into either the WAITING state or the TIMED_WAITING state.

每当一个Java线程调用join()、sleep()wait()时,它就进入WAITING状态或TIMED_WAITING状态。

In addition, a thread can interrupt another thread by calling another thread’s interrupt() method.

此外,一个线程可以通过调用另一个线程的interrupt()方法来中断另一个线程。

Consequently, the thread throws an InterruptedException if another thread interrupts it while it is in the WAITING or in the TIMED_WAITING state.

因此,线程如果在WAITINGTIMED_WAITING状态下被其他线程中断,则抛出InterruptedException

Consider the following example with two threads:

考虑以下有两个线程的例子。

  • The main thread starts the child thread and interrupts it
  • The child thread starts and calls sleep()

This scenario results in an InterruptedException:

这种情况会导致一个InterruptedException:

class ChildThread extends Thread {

    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            LOGGER.error("InterruptedException caught!");
        }
    }
}

public class MainThread {

    public static void main(String[] args) 
      throws InterruptedException {
        ChildThread childThread = new ChildThread();
        childThread.start();
        childThread.interrupt();
    }
}

4. Unchecked Exceptions

4.未检查的异常情况

For Unchecked Exceptions, the compiler doesn’t check during the compilation process. Hence, it isn’t mandatory for the method to handle these exceptions.

对于未检查的异常,编译器在编译过程中并不检查。因此,方法并不必须处理这些异常。

All unchecked exceptions extend the class RuntimeException.

所有未检查的异常都扩展了RuntimeException.类。

Let’s discuss some unchecked exceptions in detail.

让我们来详细讨论一些未检查的例外情况。

4.1. NullPointerException

4.1.NullPointerException

If an application attempts to use null where it actually requires an object instance, the method will throw a NullPointerException

如果应用程序试图在实际需要一个对象实例的地方使用null,该方法将抛出一个NullPointerException

There are different scenarios where illegal uses of null causes NullPointerException. Let’s consider some of them.

非法使用null导致NullPointerException.的情况有很多。

Calling a method of the class that has no object instance:

调用一个没有对象实例的类的方法。

String strObj = null;
strObj.equals("Hello World"); // throws NullPointerException.

Also, if an application tries to access or modify an instance variable with a null reference, we get a NullPointerException:

此外,如果一个应用程序试图访问或修改一个具有null引用的实例变量,我们会得到一个NullPointerException:

Person personObj = null;
String name = personObj.personName; // Accessing the field of a null object
personObj.personName = "Jon Doe"; // Modifying the field of a null object

4.2. ArrayIndexOutOfBoundsException

4.2.ArrayIndexOutOfBoundsException

An array stores its elements in contiguous fashion. Thus, we can access its elements via indices.

一个数组以连续的方式存储其元素。因此,我们可以通过索引访问其元素。

However, if a piece of code tries to access an illegal index of an array, the respective method throws an ArrayIndexOutOfBoundException.

然而,如果一段代码试图访问一个数组的非法索引,相应的方法会抛出一个ArrayIndexOutOfBoundException.

Let’s see a few examples that throw ArrayIndexOutOfBoundException:

让我们看看几个抛出ArrayIndexOutOfBoundException的例子。

int[] nums = new int[] {1, 2, 3};
int numFromNegativeIndex = nums[-1]; // Trying to access at negative index
int numFromGreaterIndex = nums[4];   // Trying to access at greater index
int numFromLengthIndex = nums[3];    // Trying to access at index equal to size of the array

4.3. StringIndexOutOfBoundsException

4.3.StringIndexOutOfBoundsException

The String class in Java provides the methods to access a particular character of the string or to slice out a character array out of the String. When we use these methods, internally it converts the String into a character array.

Java中的String类提供了访问字符串中某一特定字符或从String中切出一个字符数组的方法。

Again, there could be an illegal use of indexes on this array. In such cases, these methods of the String class throws the StringIndexOutOfBoundsException.

同样,在这个数组上可能存在非法使用索引的情况。在这种情况下,String类的这些方法会抛出StringIndexOutOfBoundsException

This exception indicates that the index is either greater than or equal to the size of the String. StringIndexOutOfBoundsException extends IndexOutOfBoundsException.

这个异常表示索引大于或等于字符串的大小。 StringIndexOutOfBoundsException扩展了IndexOutOfBoundsException

The method charAt(index) of the class String throws this exception when we try to access a character at the index equal to the String’s length or some other illegal index:

当我们试图在等于String长度的索引或其他非法索引处访问一个字符时,String类的charAt(index)方法会抛出这个异常。

String str = "Hello World";
char charAtNegativeIndex = str.charAt(-1); // Trying to access at negative index
char charAtLengthIndex = str.charAt(11);   // Trying to access at index equal to size of the string		

4.4. NumberFormatException

4.4.NumberFormatException

Quite often an application ends up with numeric data in a String. In order to interpret this data as numeric, Java allows the conversion of String to numeric types. The wrapper classes such as Integer, Float, etc. contains utility methods for this purpose.

很多时候,应用程序最终会在String中出现数字数据。为了将这些数据解释为数字,Java允许将String转换为数字类型。封装类,如Integer、Float等,包含了用于此目的的实用方法。

However, if the String doesn’t have an appropriate format during the conversion, the method throws a NumberFormatException.

然而,如果字符串在转换过程中没有合适的格式,该方法会抛出一个NumberFormatException。

Let’s consider the following snippet.

让我们考虑下面的片段。

Here, we declare a String with an alphanumeric data. Further, we try to use the methods of the Integer wrapper class to interpret this data as numeric.

这里,我们声明了一个带有字母数字数据的String。此外,我们尝试使用Integer包装类的方法来解释这个数据为数字。

Consequently, this results in NumberFormatException:

因此,这导致了NumberFormatException:

String str = "100ABCD";
int x = Integer.parseInt(str); // Throws NumberFormatException
int y = Integer.valueOf(str); //Throws NumberFormatException

4.5. ArithmeticException

4.5.ArithmeticException

When a program evaluates an arithmetic operation and it results in some exceptional condition, it throws ArithmeticException. In addition, ArithmeticException applies to only int and long data types.

当程序评估一个算术运算并导致一些特殊情况时,它会抛出ArithmeticException此外,ArithmeticException仅适用于intlong数据类型。

For instance, if we try to divide an integer by zero, we get an ArithmeticException:

例如,如果我们试图用一个整数除以0,我们会得到一个ArithmeticException

int illegalOperation = 30/0; // Throws ArithmeticException

4.6. ClassCastException

4.6.ClassCastException

Java allows typecasting between the objects in order to support inheritance and polymorphism. We can either upcast an object or downcast it.

Java允许在对象之间进行typecasting,以支持继承和多态性。我们既可以上投一个对象,也可以下投一个对象。

In upcasting, we cast an object to its supertype. And in downcasting, we cast an object to one of its subtypes.

在上投中,我们把一个对象投给它的上级类型。而在下投中,我们将一个对象投给它的一个子类型。

However, at runtime, if the code attempts to downcast an object to a subtype of which it isn’t an instance, the method throws a ClassCastException.

然而,在运行时,如果代码试图将一个对象下移到它不是一个实例的子类型,该方法会抛出一个ClassCastException

The runtime instance is what actually matters in typecasting. Consider the following inheritance between AnimalDog, and Lion:

在类型转换中,运行时的实例才是真正重要的。考虑以下AnimalDog和Lion之间的继承关系。

class Animal {}

class Dog extends Animal {}

class Lion extends Animal {}

Further, in the driver class, we cast the Animal reference containing an instance of Lion into a Dog.

此外,在驱动类中,我们将包含Lion实例的Animal引用转换为Dog

However, at the runtime, the JVM notices that instance Lion isn’t compatible with the subtype of the class Dog.

然而,在运行时,JVM注意到实例Lion与类Dog的子类型不兼容。

This results in ClassCastException:

这导致了ClassCastException:

Animal animal = new Lion(); // At runtime the instance is Lion
Dog tommy = (Dog) animal; // Throws ClassCastException

4.7. IllegalArgumentException

4.7.IllegalArgumentException

A method throws an IllegalArgumentException if we call it with some illegal or inappropriate arguments.

如果我们用一些非法或不适当的参数调用一个方法,就会抛出IllegalArgumentException

For instance, the sleep() method of the Thread class expects positive time and we pass a negative time interval as an argument. This results in IllegalArgumentException:

例如,Thread类的sleep()方法希望得到正的时间,而我们传递了一个负的时间间隔作为参数。这就导致了IllegalArgumentException

Thread.currentThread().sleep(-10000); // Throws IllegalArgumentException

4.8. IllegalStateException

4.8.IllegalStateException

IllegalStateException signals that a method’s been invoked at an illegal or inappropriate time.

IllegalStateException表明一个方法在非法或不适当的时间被调用。

Every Java object has a state (instance variables) and some behavior (methods). Thus, IllegalStateException means it’s illegal to invoke the behavior of this object with the current state variables.

每个Java对象都有一个状态(实例变量)和一些行为(方法)。因此,IllegalStateException意味着用当前状态变量调用这个对象的行为是非法的。

However, with some different state variables, it might be legal.

然而,如果有一些不同的状态变量,它可能是合法的。

For example, we use an iterator to iterate a list. Whenever we initialize one, it internally sets its state variable lastRet to -1.

例如,我们用一个迭代器来迭代一个列表。每当我们初始化一个迭代器时,它在内部将其状态变量lastRet设为-1。

With this context, the program tries to call the remove method on the list:

在这种情况下,程序试图调用列表上的remove方法。

//Initialized with index at -1
Iterator<Integer> intListIterator = new ArrayList<>().iterator(); 

intListIterator.remove(); // IllegalStateException

Internally, the remove method checks the state variable lastRet and if it is less than 0, it throws IllegalStateException. Here, the variable is still pointing to the value -1.

在内部,remove方法检查状态变量lastRet,如果它小于0,它会抛出IllegalStateException。在这里,该变量仍然指向值-1。

As a result, we get an IllegalStateException.

结果,我们得到一个IllegalStateException

5. Conclusion

5.结论

In this article, we first discussed what are exceptions. An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program’s instructions.

在这篇文章中,我们首先讨论了什么是异常。异常是在程序执行过程中发生的事件,它破坏了程序指令的正常流程。

Then, we categorized the exceptions into the Checked Exceptions and the Unchecked Exceptions.

然后,我们把例外情况分为已检查的例外情况和未检查的例外情况。

Next, we discussed different types of exceptions that can come up during the compile time or at the runtime.

接下来,我们讨论了在编译时或运行时可能出现的不同类型的异常。

We can find the code for this article over on GitHub.

我们可以在GitHub上找到这篇文章的代码over