异常
异常是在程序执行过程中发生的意外或异常情况。在Java中,异常是以类的形式表示的,并且它们遵循一个层次结构。异常类是从Throwable
类派生出来的,Throwable
是所有异常类的根类。
Throwable
Throwable
是所有异常类的根类。
主要方法
序号 | 方法及说明 |
---|---|
1 | public String getMessage() 返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。 |
2 | public Throwable getCause() 返回一个 Throwable 对象代表异常原因。 |
3 | public String toString() 返回此 Throwable 的简短描述。 |
4 | public void printStackTrace() 将此 Throwable 及其回溯打印到标准错误流。。 |
5 | public StackTraceElement [] getStackTrace() 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。 |
6 | public Throwable fillInStackTrace() 用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。 |
Error
Error
表示严重的系统错误,通常是由于虚拟机或底层系统出现问题而引起的。常见的Error
子类包括AssertionError
(断言错误)、OutOfMemoryError
(内存溢出错误)、StackOverflowError
(栈溢出错误)等。这些错误通常是不可恢复的,程序通常不捕获错误。
Exception
Exception
是可检查异常的父类,表示程序中可能出现的可预见问题。它又有两个主要的子类:RuntimeException
和其他非RuntimeException
的异常。
Checked Exception
非RuntimeException
的异常称为受检异常,编译器会强制要求处理或声明对它们的处理。
Runtime Exception
RuntimeException
及其子类表示编程错误或逻辑错误,通常不需要显式地捕获或声明处理。
RuntimeException
的常见子类包括NullPointerException
(空指针异常)、IllegalArgumentException
(非法参数异常)、IndexOutOfBoundsException
(索引越界异常)、ArrayIndexOutOfBoundsException
(数组索引越界异常)、ClassCastException
(类型转换异常)、UnsupportedOperationException
(不支持的操作异常)等。
类别 | 异常类名 | 描述 |
---|---|---|
错误 | Error | 表示严重的系统错误,通常由虚拟机或底层系统出现的问题引起。 |
AssertionError | 表示断言失败。 | |
OutOfMemoryError | 表示内存溢出错误。 | |
StackOverflowError | 表示栈溢出错误。 | |
检查性异常 | Exception | 表示可检查异常的根类。 |
IOException | 表示输入/输出操作出错。 | |
FileNotFoundException | 表示文件未找到。 | |
ClassNotFoundException | 表示未找到类。 | |
运行时异常 | RuntimeException | 表示不可检查异常的根类,通常由编程或逻辑错误引起。 |
NullPointerException | 表示空指针引用。 | |
IllegalArgumentException | 表示非法参数。 | |
IndexOutOfBoundsException | 表示索引越界。 | |
ArrayIndexOutOfBoundsException | 表示数组索引越界。 | |
ClassCastException | 表示类型转换错误。 | |
UnsupportedOperationException | 表示不支持的操作。 | |
ArithmeticException | 表示异常的运算条件 |
异常处理
异常处理是一种机制,用于在程序运行时检测和处理意外或异常情况。当异常发生时,程序可以通过异常处理机制捕获和处理异常,以便采取适当的措施来处理异常情况。
异常处理的语法
Java中的异常处理是通过以下关键字和语句实现的:
-
try-catch
语句块:try-catch
语句块用于捕获和处理异常。try
块中包含可能引发异常的代码,而catch
块用于捕获和处理异常。一个try
块可以有多个catch
块,每个catch
块负责捕获特定类型的异常。try { // 可能引发异常的代码 } catch (ExceptionType1 e1) { // 处理 ExceptionType1 类型的异常 } catch (ExceptionType2 e2) { // 处理 ExceptionType2 类型的异常 } finally { // 可选的 finally 块 }
注意:上述示例中若
ExceptionType1
与ExceptionType2
存在继承关系,则catch块的顺序遵循“先子类后父类”的原则,因为如果先处理父类异常的catch块,那么在该catch块之后的子类catch块将无法捕获到已经被父类catch块处理过的子类异常。注意下面事项:
- catch 不能独立于 try 存在。
- 在 try/catch 后面添加 finally 块并非强制性要求的。
- try 代码后不能既没 catch 块也没 finally 块。
- try, catch, finally 块之间不能添加任何代码。
也可以在一个
catch
块中使用|
符号来捕获多个异常类型。下面是一个示例:try { // 可能引发异常的代码 } catch (ExceptionType1 | ExceptionType2 | ExceptionType3 e) { // 处理 ExceptionType1、ExceptionType2 和 ExceptionType3 类型的异常 }
在上面的示例中,使用了
|
符号将多个异常类型组合在一起,以便在单个catch
块中捕获这些异常类型。当任何一个异常类型匹配时,该catch
块将处理异常。使用|
符号捕获多个异常类型是在Java 7中引入的新功能。它提供了一种更简洁的方式来处理多个相关异常类型的情况。这些异常类型可以是不相关的,只要它们与try
块中可能抛出的异常类型匹配即可。否则,编译器将报错。在
catch
块中,可以根据需要处理异常、记录日志、提供错误消息等。 -
throw
语句:throw
语句用于手动抛出异常。可以使用throw
语句在程序的任何地方抛出自定义异常或Java提供的异常。throw new ExceptionType("Error message");
-
throws
关键字:throws
关键字用于声明一个方法可能抛出的异常。当方法可能抛出异常时,可以使用throws
关键字在方法声明中指定异常类型。void methodName() throws ExceptionType1, ExceptionType2 { // 方法体 }
-
finally
关键字finally
关键字用来创建在try
代码块后面执行的代码块。无论是否发生异常,
finally
代码块中的代码总会被执行。在
finally
代码块中,可以运行清理类型等收尾善后性质的语句。finally
代码块出现在catch
代码块最后。当
finally
块存在时,它会在return
语句执行之前执行。这意味着无论return
语句在try
块或catch
块中执行,finally
块中的代码都会在方法返回之前执行。以下是一个示例:
public int someMethod() { try { // 可能引发异常的代码 return 1; } catch (Exception e) { // 处理异常 return 2; } finally { // 在这里执行清理操作或释放资源的代码 System.out.println("Finally block executed."); } }
在上面的示例中,如果没有发生异常,
try
块中的代码将被执行,并且方法将返回1。然后,finally
块中的代码会在方法返回之前执行,并打印出"Finally block executed."。如果在
try
块中发生了异常,catch
块中的代码将被执行,并且方法将返回2。然后,finally
块中的代码仍然会在方法返回之前执行,并打印出"Finally block executed."。总之,无论
return
语句在try
块、catch
块还是方法的其他位置执行,finally
块中的代码都会在方法返回之前执行。这使得你可以在方法返回之前执行必要的清理操作或释放资源。
自定义异常
在Java中,可以创建自定义异常类来表示特定的异常情况。自定义异常类应该继承自Exception
或其子类,或者实现Throwable
接口。
以下是一个自定义异常类的示例:
public class MyCustomException extends Exception {
public MyCustomException() {
super();
}
public MyCustomException(String message) {
super(message);
}
public MyCustomException(String message, Throwable cause) {
super(message, cause);
}
}
在上面的示例中,MyCustomException
类继承自Exception
类,它是一个受检查异常。它提供了多个构造函数,可以传递异常消息和可选的原因(Throwable
对象)。
可以根据自己的需求,添加自定义的字段、方法和构造函数到自定义异常类中,以便更好地表示特定的异常情况。
在代码中,当你需要抛出自定义异常时,可以使用throw
关键字将其抛出:
public void someMethod() throws MyCustomException {
// 某些逻辑
if (someCondition) {
throw new MyCustomException("发生了自定义异常");
}
// 其他逻辑
}
在上面的示例中,someMethod
方法定义了可能抛出MyCustomException
的异常情况。当someCondition
满足时,会创建并抛出一个MyCustomException
对象。
当调用someMethod
时,如果抛出了MyCustomException
,则需要在调用处处理或继续抛出该异常。
自定义异常类可以帮助你更好地组织和处理特定的异常情况,使代码更具可读性和可维护性。
集合
集合(Collections)是指一组对象的容器,用于以更方便的方式管理和操作这些对象。集合提供了一种存储和处理数据的方式,可以动态地增加或减少元素的数量。Java的集合框架提供了一组接口和类来表示和操作不同类型的集合。
在Java集合框架中,集合类被分为三类:List
、Set
和Queue
。其中,List
是有序集合,允许重复元素;Set
是无序集合,不允许重复元素;而Queue
是一种特殊的集合,按照先进先出(FIFO)的方式处理元素。
常见的集合类有ArrayList
、LinkedList
、HashSet
和TreeSet
等。ArrayList
和LinkedList
实现了List
接口,HashSet
和TreeSet
实现了Set
接口,而Queue
接口则由LinkedList
和ArrayDeque
等实现。
Collection接口
Collection接口是Java集合框架的根接口,它扩展了Iterable
接口,定义了对集合进行添加、删除、遍历等操作的方法。Collection接口是List、Set和Queue接口的父接口,它提供了一组通用的方法,用于操作集合中的元素。
Collection接口中的常用方法包括:
add(E element)
:将元素添加到集合中。remove(Object element)
:从集合中移除指定元素。contains(Object element)
:判断集合是否包含指定元素。size()
:返回集合中的元素数量。isEmpty()
:判断集合是否为空。iterator()
:返回一个用于迭代集合的迭代器。
Collection接口的常见实现类有ArrayList
、LinkedList
和HashSet
等。
Collections工具类
Collections
是 Java 提供的一个工具类,位于 java.util
包中。它包含了一系列静态方法,用于对集合进行操作和处理。Collections
类提供了一些常用的算法和工具方法,如排序、查找、反转、填充等,用于操作和处理集合对象。
Map接口
Map接口表示一个键值对(key-value)的映射关系。它提供了通过键来查找值、插入、删除和遍历键值对的操作。Map中的键是唯一的,而值可以重复。
Map接口中的常用方法包括:
put(K key, V value)
:向Map中插入键值对。get(Object key)
:通过键获取对应的值。remove(Object key)
:从Map中移除指定键的键值对。containsKey(Object key)
:判断Map中是否包含指定的键。containsValue(Object value)
:判断Map中是否包含指定的值。size()
:返回Map中键值对的数量。
Map接口的常见实现类有HashMap
、TreeMap
和LinkedHashMap
等。
扩展
集合和集合框架
集合是指一组对象的容器,用于以更方便的方式管理和操作这些对象。集合提供了一种存储和处理数据的方式,可以动态地增加或减少元素的数量。集合框架是Java提供的用于表示和操作不同类型集合的一组接口和类的集合。它提供了一套丰富的数据结构和算法,使得开发者可以方便地处理和操作集合中的元素。
Collection接口和Map接口的区别
- Collection接口表示一组对象的集合,它是Java集合框架的根接口。它可以包含重复的元素,并且提供了对集合进行添加、删除、遍历等操作的方法。常见的实现类有List、Set和Queue。
- Map接口表示一组键值对(key-value)的映射关系。它提供了通过键来查找值、插入、删除和遍历键值对的操作。Map中的键是唯一的,而值可以重复。常见的实现类有HashMap、TreeMap和LinkedHashMap。
总结:
- Collection接口用于表示一组对象的集合,可以包含重复元素。它提供了对集合进行添加、删除、遍历等操作的方法。
- Map接口用于表示键值对的映射关系,其中每个键都是唯一的。它提供了通过键来查找值、插入、删除和遍历键值对的操作。
在使用上的区别是,Collection接口操作的是集合中的元素,而Map接口操作的是键值对。
Collection和Collections的区别
Collection
是一个接口,用于表示一组对象的集合,定义了对集合进行操作的方法。Collections
是一个工具类,提供了一系列静态方法,用于对集合进行操作和处理。