一文详解Java中三大异常处理方式(try-catch、throw、throws)
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>前言</li><li>1. try-catch:自己处理(捕获与解决)</li><ul class="second_class_ul"><li>语法详解</li></ul><li>2. throw:主动制造(抛出异常)</li><ul class="second_class_ul"><li>语法详解</li></ul><li>3. throws:声明推卸(声明异常)</li><ul class="second_class_ul"><li>语法详解</li></ul><li>总结串联:它们是如何配合工作的?</li><ul class="second_class_ul"></ul><li>总结对比</li><ul class="second_class_ul"></ul></ul></div><p class="maodian"></p><h2>前言</h2><p>这三种方式(<code>try-catch</code>、<code>throw</code>、<code>throws</code>)是 Java 异常处理的三大基石。要搞懂它们,最重要的是明白<strong>它们分别处于异常处理流程中的哪个环节</strong>。</p>
<p class="maodian"></p><h2>1. try-catch:自己处理(捕获与解决)</h2>
<p>这是 Java 处理异常最直接的方式,用于在代码内部捕获异常并进行处理,从而保证程序能继续运行。</p>
<ul><li><strong>定义位置</strong>:方法体内部。</li><li><strong>结构组成</strong>:由 <code>try</code> 块和一个或多个 <code>catch</code> 块组成(还可以包含 <code>finally</code> 块)。</li><li><strong>执行逻辑</strong>:<ol><li><strong>try 块</strong>:包裹可能抛出异常的代码段。程序正常执行时,逐行执行 try 块内的代码。</li><li><strong>异常触发</strong>:如果 try 块中的某行代码抛出异常,try 块中剩余的代码将不再执行,程序立即跳转到与异常类型匹配的 <code>catch</code> 块。</li><li><strong>catch 块</strong>:捕获特定类型的异常对象。在 catch 块中编写处理该异常的逻辑(如日志记录、恢复操作、提示用户等)。如果没有异常发生,catch 块将被跳过。</li></ol></li><li><strong>作用</strong>:将异常处理逻辑与正常业务逻辑分离,防止因异常导致程序非正常终止。</li></ul>
<p class="maodian"></p><p class="maodian"></p><p class="maodian"></p><h3>语法详解</h3>
<div class="jb51code"><pre class="brush:java;">try {
// 1. try 块:放可能出现问题的代码( risky code )
int result = 10 / 0; // 这里会抛出 ArithmeticException 异常
System.out.println("这行代码不会执行,因为上面出错了");
} catch (ArithmeticException e) {
// 2. catch 块:如果 try 里的代码真的出错了,就会跳到这里来执行
System.out.println("哎呀,除数不能为0!补救措施:把除数改为1");
// e 就是捕获到的那个异常对象,你可以用它打印错误信息
e.printStackTrace();
}
System.out.println("程序继续运行...");
</pre></div>
<ul><li><strong>关键点</strong>:
<ul><li><strong>try</strong>:监控代码。</li><li><strong>catch</strong>:匹配异常类型(如 <code>ArithmeticException</code>)。如果 try 里抛出的异常和 catch 括号里的类型一致(或是其子类),就进入 catch 块执行。</li><li><strong>执行顺序</strong>:一旦 try 中某行出错,直接跳过 try 剩余代码,进入对应的 catch。</li><li><strong>多重 catch</strong>:你可以写多个 <code>catch</code> 来处理不同的异常,就像准备不同的急救包。</li></ul></li></ul>
<p>补充:</p>
<p>finally:最终执行块</p>
<ul><li><strong>定义</strong>:位于 <code>try-catch</code> 结构之后的代码块。</li><li><strong>核心特性</strong>:无论 <code>try</code> 块中是否发生异常,也无论是否执行了 <code>return</code> 语句,<code>finally</code> 块中的代码<strong>一定会执行</strong>。</li><li><strong>主要作用</strong>:用于<strong>资源释放</strong>。通常在代码执行完毕后,关闭文件流、数据库连接或释放锁,确保不占用系统资源。</li><li><strong>唯一例外</strong>:如果在 <code>try</code> 或 <code>catch</code> 中执行了 <code>System.exit(0)</code> 强制终止 JVM,或者发生了断电宕机,<code>finally</code> 才不会执行。</li></ul>
<p class="maodian"></p><h2>2. throw:主动制造(抛出异常)</h2>
<p>这是一个动作关键字,用于在代码中显式地生成并抛出一个异常对象。它不是“处理”异常,而是“制造”异常。</p>
<ul><li><strong>定义位置</strong>:方法体或代码块内部。</li><li><strong>操作对象</strong>:后面必须跟一个 <code>Throwable</code> 类及其子类的实例化对象。</li><li><strong>执行逻辑</strong>:<ol><li>程序执行到 <code>throw</code> 语句时,会立即停止当前方法的后续代码执行。</li><li>它将创建的异常对象抛出给 Java 运行时系统。</li><li>如果该 <code>throw</code> 语句未包裹在 <code>try-catch</code> 块中,或者 <code>catch</code> 块未捕获该异常,则该方法将立即结束,并将异常抛给该方法的调用者。</li></ol></li><li><strong>作用</strong>:通常用于业务逻辑校验。当程序状态不符合预期(如参数非法、状态错误)时,主动中断流程并向上层报告错误。</li></ul>
<h3>语法详解</h3>
<div class="jb51code"><pre class="brush:java;">public void checkAge(int age) {
// 逻辑判断:如果年龄是负数,这不符合逻辑
if (age < 0) {
// 主动创建一个异常对象,并用 throw 关键字抛出
// 就像你主动点燃了引信,扔出手雷
throw new IllegalArgumentException("年龄不能是负数!");
}
System.out.println("年龄检查通过:" + age);
}
</pre></div>
<ul><li><strong>关键点</strong>:
<ul><li><code>throw</code> 写在方法<strong>内部</strong>。</li><li><code>throw</code> 后面必须跟一个<strong>异常对象</strong>(<code>new ...</code>)。</li><li>一旦执行到 <code>throw</code>,<strong>当前方法立即结束</strong>(就像遇到 <code>return</code> 一样),后面的代码不再执行,控制权交给调用者。</li></ul></li></ul>
<p class="maodian"></p><h2>3. throws:声明推卸(声明异常)</h2>
<p>这是一个声明关键字,用在方法签名上。它表示当前方法不处理某些异常,而是将异常的处理责任推给调用该方法的上层代码。</p>
<ul><li><strong>定义位置</strong>:方法声明中,参数列表之后,方法体之前。</li><li><strong>操作对象</strong>:后面跟异常类名(可以多个,用逗号分隔),不是对象实例。</li><li><strong>执行逻辑</strong>:<ol><li>声明该方法在执行过程中可能会抛出指定类型的异常。</li><li>当调用者调用该方法时,编译器会强制要求调用者必须处理这些声明的异常(通过 <code>try-catch</code> 捕获,或者在自身的声明中使用 <code>throws</code> 继续向上抛出)。</li></ol></li><li><strong>作用</strong>:明确了方法的风险边界,实现了异常处理的传递(冒泡机制),让方法的调用者决定如何处理底层发生的异常。</li></ul>
<h3>语法详解</h3>
<div class="jb51code"><pre class="brush:java;">// 在方法定义时,使用 throws 关键字声明可能抛出的异常列表
// 告诉调用者:调用我时,可能会遇到 FileNotFoundException,你自己看着办!
public void readFile(String filePath) throws FileNotFoundException {
// 这里不需要 try-catch
// 如果文件真的找不到,JVM 会抛出 FileNotFoundException
// 这个异常会顺着调用链,扔给调用 readFile 的人去处理
FileInputStream fis = new FileInputStream(filePath);
}
</pre></div>
<ul><li><strong>调用者怎么处理?</strong><br />当别人调用 <code>readFile</code> 方法时,编译器会强制要求调用者处理这个异常(要么 <code>try-catch</code> 接住,要么继续 <code>throws</code> 往上甩)。</li></ul>
<div class="jb51code"><pre class="brush:java;">public static void main(String[] args) {
try {
// 调用者必须用 try-catch 包裹,或者 main 方法也 throws
readFile("test.txt");
} catch (FileNotFoundException e) {
System.out.println("文件没找到,我负责处理:新建一个文件");
}
}
</pre></div>
<ul><li><strong>关键点</strong>:
<ul><li><code>throws</code> 写在方法声明<strong>后面</strong>(括号外面)。</li><li>后面跟的是异常<strong>类名</strong>(可以多个,用逗号隔开),不是对象。</li><li>它是一种**“甩锅”**机制:将异常的处理责任转移给上层调用者。</li></ul></li></ul>
<p class="maodian"></p><h2>总结串联:它们是如何配合工作的?</h2>
<p>让我们把这三个关键词串联在一个完整的业务逻辑中:</p>
<p>假设我们有一个<strong>银行转账</strong>的功能:</p>
<div class="jb51code"><pre class="brush:java;">public class BankService {
// 1. throws 声明:
// 这个方法告诉外界:“我可能会遇到钱不够的情况,调用者要准备好处理”
public void transfer(double amount) throws InsufficientFundsException {
if (amount < 0) {
// 2. throw 抛出:
// 程序员发现逻辑错误(转账金额为负),主动制造异常扔出去
throw new IllegalArgumentException("转账金额不能是负数!");
}
if (balance < amount) {
// 3. throw 抛出:
// 发现余额不足,主动制造一个“余额不足异常”扔出去
// 因为方法签名上有 throws,这里可以直接扔,不用自己 catch
throw new InsufficientFundsException("余额不足,转账失败");
}
// 正常扣款逻辑...
}
}
// 调用者
public class Main {
public void doTransfer() {
BankService bank = new BankService();
// 4. try-catch 捕获:
// 因为 bank.transfer() 声明了会扔出异常,所以这里必须接住
try {
bank.transfer(1000);
} catch (InsufficientFundsException e) {
// 处理余额不足的情况
System.out.println("提示用户:充值");
} catch (IllegalArgumentException e) {
// 处理参数错误的情况
System.out.println("提示用户:金额非法");
}
}
}
</pre></div>
<p class="maodian"></p><h2>总结对比</h2>
<table><thead><tr><th>关键字</th><th>类别</th><th>出现位置</th><th>核心作用</th></tr></thead><tbody><tr><td><strong>try-catch</strong></td><td>处理机制</td><td>方法体内部</td><td><strong>拦截</strong>异常,就地解决,保证当前流程不中断。</td></tr><tr><td><strong>throw</strong></td><td>动作</td><td>方法体内部</td><td><strong>制造</strong>异常,显式抛出一个异常对象,中断当前流程。</td></tr><tr><td><strong>throws</strong></td><td>声明</td><td>方法签名上</td><td><strong>声明</strong>异常,告知上层调用者这里可能出错,需由调用者处理。</td></tr></tbody></table>
<p>到此这篇关于Java中三大异常处理方式(try-catch、throw、throws)的文章就介绍到这了,更多相关Java异常处理try-catch、throw、throws内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
<div class="art_xg">
<b>您可能感兴趣的文章:</b><ul><li>Java中的异常处理机制try-catch详解</li><li>Java中的异常处理之try-catch使用详解</li><li>JAVA中try-catch结构之异常处理的使用方法</li><li>java异常:异常处理--try-catch结构详解</li><li>Spring Boot异常处理try-catch应该怎么使用?</li></ul>
</div>
</div>
<!--endmain-->
頁:
[1]