异常-Exception
Java语言中,将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法错误和逻辑错误不是异常)
执行过程中所发生的异常事件可分为两大类
1)Error(错误):Java虚拟机无法解决的严重问题。如JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError(栈溢出)和OOM(out of memory),Error是严重错误,程序会崩溃。
2)Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件等等,Exception分为两大类:运行时异常和编译时异常。
常见的运行时异常
NullPointerException(空指针异常)
当应用程序试图在需要对象的地方使用 null,这种异常就会发生。例如,调用 null 对象的实例方法、访问 null 对象的属性、计算 null 对象的长度、使用 throw 语句抛出 null 等情况。
Object obj = null;
obj.toString(); // 这将抛出 NullPointerException
ArithmeticException(数学运算异常)
- 当出现异常的运算条件时,例如除以零,这种异常就会发生。
int result = 10 / 0; // 这将抛出 ArithmeticException
ArrayIndexOutOfBoundsException(数组下标越界异常)
如果数组的索引为负或大于等于数组大小,那么这种异常就会发生。
int[] array = new int[10];
int number = array[10]; // 这将抛出 ArrayIndexOutOfBoundsException
ClassCastException(类型转换异常)
当试图将对象强制转换为不是实例的子类时,这种异常就会发生。
Object x = new Integer(0);
System.out.println((String)x); // 这将抛出 ClassCastException
NumberFormatException(数字格式异常)
当试图将一个不适合特定数字格式的字符串转换为该格式的数字时,这种异常就会发生。
int num = Integer.parseInt("XYZ"); // 这将抛出 NumberFormatException
以上这些都是运行时异常,也就是 RuntimeException 的子类,Java编译器不会检查它们。但是,良好的编程和设计实践通常是尽量避免这些异常的发生,或者在它们发生时能够适当地处理。
常见的编译异常
IOException
这是发生I/O错误产生的异常,比如读写文件时发生的异常。这类异常通常涉及到文件、网络、数据库等I/O操作。
try {
FileReader reader = new FileReader("somefile.txt");
} catch (IOException e) {
e.printStackTrace();
}
SQLException
这是处理数据库操作时可能发生的异常。
try {
connection = DriverManager.getConnection("jdbc:mysql://localhost/test", "user", "password");
} catch (SQLException e) {
e.printStackTrace();
}
ClassNotFoundException
当应用程序试图通过字符串名称加载类,而在类路径中找不到这个类时,抛出该异常。
try {
Class.forName("com.example.NonExistentClass");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
NoSuchMethodException 和 NoSuchFieldException
当访问一个不存在的方法或字段时,抛出这类异常。
try {
Class clazz = Class.forName("java.lang.String");
Method method = clazz.getMethod("nonExistentMethod");
} catch (NoSuchMethodException | ClassNotFoundException e) {
e.printStackTrace();
}
InterruptedException
当一个线程处于睡眠、等待或占用,并且被中断时,抛出该异常。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
这些都是必须处理的异常,如果不处理,编译器就会报错。这是Java设计者为了提高Java程序的健壮性而采取的一种策略,通过强制程序员处理可能出现的异常,使得Java程序能更好地应对错误情况。
异常处理机制
try-catch
try-catch
是Java中用来捕获和处理异常的主要机制。
try
块包含可能会抛出异常的代码。如果在try
块中的代码抛出了异常,那么与之匹配的catch
块就会被执行。catch
块用于捕获和处理特定类型的异常。你可以为不同类型的异常提供不同的catch
块。finally
块是可选的,包含在任何情况下都需要执行的代码,无论是否发生异常。
try {
// 可能会抛出异常的代码
} catch (IOException e) {
// 处理IOException的代码
} catch (SQLException e) {
// 处理SQLException的代码
} finally {
// 无论是否发生异常都会执行的代码
}
快捷键:ctrl + atl + t
throws
throws关键字用于在方法声明中指示该方法可能会抛出哪些类型的异常。这些异常可能是Java库中的异常,也可能是你自定义的异常。使用throws关键字可以将异常的处理责任传递给方法的调用者。
在方法中声明用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类
public void readFile() throws Exception {
// 可能会抛出Exception的代码
}
注意事项:
1)对于编译异常,程序中必须处理(使用try-catch或者throws)。
2)对于运行时异常,程序中如果没有处理,默认就是throws的方式处理。
3)子类重写父类的方法时,所抛出的异常要么与父类抛出的异常一致,要么为父类抛出异常的子类型。
4)在throws过程中,如果有try-catch,就相当于异常处理,就不必使用throws。
自定义异常
在Java中,可以通过继承现有的异常类来创建自定义异常。自定义异常可以让你更准确地表示程序中可能出现的特定错误条件,这有助于提高代码的可读性和可维护性。
创建自定义异常通常涉及以下步骤:
- 创建一个新的类,这个类应该继承自
Exception
类(用于编译时异常)或RuntimeException
类(用于运行时异常)。 - 添加构造方法,这些构造方法应该调用父类的构造方法。通常,你至少需要提供两个构造方法:一个无参数的构造方法,和一个带有字符串参数的构造方法。字符串参数用于提供关于异常的详细信息。
- (可选)添加自定义字段和方法,这些字段和方法可以提供关于异常的额外信息。
以下是一个自定义异常的例子:
public class CustomException {
public static void main(String[] args) throws AgeException {
int age = 180;
//要求范围在 18 – 120 之间,否则抛出一个自定义异常
if(!(age >= 18 && age <= 120)) {
//这里我们可以通过构造器,设置信息
throw new AgeException("年龄需要在 18~120 之间");
}
System.out.println("你的年龄范围正确.");
}
}
class AgeException extends RuntimeException {
public AgeException(String message) { //构造器
super(message);
}
}
throw 和 throws 的区别: