ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Java throw 和 throws 详解:异常抛出的两种姿势

Java throw 和 throws 详解:异常抛出的两种姿势 1. 引言在 Java 异常处理体系中throw和throws是两个极易混淆的关键字。它们虽然都跟「抛出异常」有关但一个负责「实际抛出」一个负责「声明可能抛出」作用位置和语法完全不同。本文将从语法、使用场景、区别对比到实战案例帮你彻底理清这两个关键字。2. throw真正把异常抛出去throw用在方法体内用于手动抛出一个异常对象。一旦执行到throw语句程序立即中断当前流程异常对象会被抛给调用方。2.1 基本语法thrownew异常类型(异常描述信息);throw后面必须跟一个Throwable或其子类的实例通常是new出来的异常对象。2.2 简单示例publicclassThrowDemo{publicstaticvoidmain(String[]args){intage-5;if(age0){thrownewIllegalArgumentException(年龄不能为负数age);}System.out.println(年龄age);}}运行结果Exception in thread main java.lang.IllegalArgumentException: 年龄不能为负数-5 at ThrowDemo.main(ThrowDemo.java:5)可以看到throw一旦执行后面的代码不再运行异常直接抛给 JVM 并打印堆栈信息。2.3 自定义异常配合 throw实际开发中throw经常配合自定义异常使用让业务错误更清晰classInsufficientBalanceExceptionextendsException{publicInsufficientBalanceException(Stringmessage){super(message);}}publicclassAccountService{publicvoidwithdraw(doublebalance,doubleamount)throwsInsufficientBalanceException{if(amountbalance){thrownewInsufficientBalanceException(余额不足当前余额balance);}System.out.println(取款成功amount);}}3. throws声明方法可能抛出的异常throws用在方法声明处用于声明该方法可能抛出的异常类型告诉调用方「调用我时请做好准备」。它本身并不抛出异常只是「预告」。3.1 基本语法访问修饰符 返回类型 方法名(参数列表)throws异常类型1,异常类型2{// 方法体}多个异常类型用逗号分隔。3.2 简单示例importjava.io.FileInputStream;importjava.io.FileNotFoundException;publicclassThrowsDemo{publicstaticvoidreadFile(Stringpath)throwsFileNotFoundException{FileInputStreamfisnewFileInputStream(path);System.out.println(文件打开成功);}publicstaticvoidmain(String[]args){try{readFile(D:/test.txt);}catch(FileNotFoundExceptione){System.out.println(文件不存在e.getMessage());}}}readFile方法声明了throws FileNotFoundException调用方main就必须处理try-catch 或继续向上 throws。4. throw 与 throws 的核心区别对比项throwthrows位置方法体内方法声明处作用真正抛出一个异常对象声明方法可能抛出的异常类型后面跟什么一个异常对象new出来的实例一个或多个异常类型类名执行时机运行时执行到才触发编译期声明不实际执行数量一次只能抛一个异常对象一次可声明多个异常类型是否中断程序是立即中断当前流程否只是声明一句话总结throw是「做」throws是「说」。5. 两者如何配合使用throws和throw经常成对出现方法内部用throw抛出异常方法签名上用throws声明这个异常让调用方感知并处理。publicclassTransferService{// 方法签名声明可能抛出的异常publicvoidtransfer(doublefromBalance,doubleamount)throwsInsufficientBalanceException{if(amount0){// 方法体内真正抛出异常thrownewIllegalArgumentException(转账金额必须大于 0);}if(amountfromBalance){thrownewInsufficientBalanceException(余额不足);}System.out.println(转账成功amount);}publicstaticvoidmain(String[]args){TransferServiceservicenewTransferService();try{service.transfer(100,200);}catch(InsufficientBalanceExceptione){System.out.println(转账失败e.getMessage());}catch(IllegalArgumentExceptione){System.out.println(参数错误e.getMessage());}}}6. 常见误区与注意事项6.1 运行时异常不需要 throwsRuntimeException及其子类如NullPointerException、IllegalArgumentException属于非受检异常编译器不强制要求声明或捕获publicvoidcheck(intnum){// 不写 throws 也合法if(num0){thrownewIllegalArgumentException(参数不能为负);}}6.2 受检异常必须处理非运行时异常受检异常要么用 try-catch 捕获要么用throws向上声明二选一否则编译不通过。6.3 throws 可以声明并未实际抛出的异常throws只是声明方法体内即使没有真正抛出该异常也合法但一般不推荐这样写容易误导调用方。6.4 子类重写方法的 throws 限制子类重写父类方法时throws声明的异常范围不能比父类更宽只能声明父类方法异常的子集或相同异常classParent{publicvoiddoWork()throwsIOException{}}classChildextendsParent{// 合法声明更具体的异常OverridepublicvoiddoWork()throwsFileNotFoundException{}// 不合法声明了更宽泛的异常编译报错// Override// public void doWork() throws Exception {// }}7. 总结throw在方法体内真正抛出一个异常对象立即中断流程。throws在方法声明处声明可能抛出的异常类型提醒调用方处理。两者常配合使用方法内throw抛出方法签名throws声明。运行时异常不强制throws受检异常必须处理或声明。子类重写时throws范围不能比父类更宽。掌握这两个关键字的区别是写出健壮、可读性高的 Java 异常处理代码的基础。希望本文能帮你彻底告别「throw 和 throws 傻傻分不清」的困扰。
返回列表