throw 和 throws 有啥区别?直接 try catch 不好吗,为啥还要抛呢?
参考回答
throw
和 throws
的区别:
throw
throw
用于在方法内部 抛出异常。- 通常用来手动创建并抛出一个异常对象。
throws
throws
用于方法的声明部分,表示该方法 可能抛出异常。- 调用该方法时,必须处理这些异常(通过
try-catch
或进一步声明throws
)。
直接用 try-catch
不好吗?为什么还要抛?
try-catch
适合在 方法内部捕获并处理异常。- 如果某个方法无法处理异常,或异常应该由调用者处理,则使用
throws
进行抛出。
示例代码:
public class Main {
public static void main(String[] args) {
try {
divide(4, 0); // 调用时捕获异常
} catch (ArithmeticException e) {
System.out.println("Exception caught: " + e.getMessage());
}
}
// 方法声明可能抛出异常
public static int divide(int a, int b) throws ArithmeticException {
if (b == 0) {
throw new ArithmeticException("Division by zero is not allowed"); // 抛出异常
}
return a / b;
}
}
输出结果:
Exception caught: Division by zero is not allowed
详细讲解与拓展
1. throw
的详细讲解
throw
语句用于 实际抛出异常。- 它后面必须跟一个异常对象。
- 常见用法是通过
new
创建异常对象:
throw new IllegalArgumentException("Invalid argument");
注意:
- 一旦执行到
throw
语句,程序的执行流程会中断,直接跳转到最近的catch
块。 - 如果没有捕获异常,程序会终止。
示例:throw
使用
public class Main {
public static void main(String[] args) {
checkAge(15);
}
public static void checkAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("Age must be 18 or above");
}
System.out.println("Age is valid");
}
}
输出结果:
Exception in thread "main" java.lang.IllegalArgumentException: Age must be 18 or above
2. throws
的详细讲解
throws
关键字用于方法声明,告诉调用者:这个方法可能抛出异常。- 它不会实际抛出异常,只是标记一种可能性,异常仍需在方法内部通过
throw
抛出。
示例:throws
使用
public class Main {
public static void main(String[] args) {
try {
readFile("nonexistent.txt");
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
}
}
public static void readFile(String fileName) throws Exception {
throw new Exception("File not found"); // 抛出异常
}
}
注意:
- 如果方法声明了
throws
,调用者必须用try-catch
处理异常,或者在其方法中继续声明throws
。
3. 直接用 try-catch
不好吗?为什么还要抛呢?
- 异常需要由更高层处理:
- 某些异常(例如数据库连接失败、文件不存在)需要由调用者或业务逻辑层处理。
- 直接用
try-catch
捕获后,可能会让异常处理过早,失去了灵活性。
示例:让调用者处理异常
public class Main {
public static void main(String[] args) {
try {
processPayment(500);
} catch (Exception e) {
System.out.println("Payment failed: " + e.getMessage());
}
}
public static void processPayment(int amount) throws Exception {
if (amount > 100) {
throw new Exception("Amount exceeds limit");
}
System.out.println("Payment processed");
}
}
- 逻辑分工:
- 一些方法负责完成特定功能,异常处理的逻辑应该交给调用者负责。
- 使用
throws
能让异常在程序中逐层传播,由最终能处理它的代码来解决。
- 日志记录与统一处理:
- 如果所有异常都直接用
try-catch
,日志记录和异常处理的逻辑会散布在各处,难以维护。 - 抛出异常可以让调用链中的高层逻辑进行统一处理。
- 如果所有异常都直接用
示例:统一处理异常
public class Main {
public static void main(String[] args) {
try {
service();
} catch (Exception e) {
System.out.println("Error occurred: " + e.getMessage());
}
}
public static void service() throws Exception {
dao(); // 让异常传播到调用者
}
public static void dao() throws Exception {
throw new Exception("Database connection failed");
}
}
拓展知识
- 检查异常和非检查异常
- 检查异常(Checked Exception)
:
- 必须用
throws
声明或try-catch
捕获。 - 例如:
IOException
、SQLException
。
- 必须用
- 非检查异常(Unchecked Exception)
:
- 不需要强制捕获或声明。
- 例如:
NullPointerException
、IllegalArgumentException
。
- 自定义异常
- 开发中可以自定义异常,继承
Exception
或RuntimeException
。 - 如果继承
Exception
,则属于检查异常,必须声明或捕获。 - 如果继承
RuntimeException
,则属于非检查异常,不强制处理。
示例:自定义异常
class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
public class Main {
public static void main(String[] args) {
try {
validateInput(-5);
} catch (CustomException e) {
System.out.println("Caught exception: " + e.getMessage());
}
}
public static void validateInput(int value) throws CustomException {
if (value < 0) {
throw new CustomException("Value cannot be negative");
}
}
}