throw关键字
-
作用:可以使用throw关键字在指定的方法中抛出指定的异常
-
使用格式:
复制 | throw new xxxException(“异常产生的原因“) |
-
注意事项
- throw关键字必须写在方法的内部
- throw关键字后边new的对象必须是 Exception或者 Exception的子类对象
- throw关键字抛出指定的异常对象,我们就必须处理这个异常对象。
- throw关键字后边创建的是 RuntimeException或者是RuntimeException的子类对象,我们可以不处理,默认交给JW处理(打印异常对象,中断程序)
- throw关键字后边创建的是编译异常,我们就必须处理这个异常,要么 throws,要么try...catch
举例
例子1
复制 | public class DemoThrow { |
| public static void main(String[] args) { |
| int[] array = {}; |
| |
| int element = DemoThrow.getElement(array, 1); |
| } |
| |
| public static int getElement(int[] array, int index) { |
| if (array.length == 0) { |
| throw new NullPointerException("传入的数组为空"); |
| } else if (index == 0 || index > array.length - 1) { |
| throw new ArrayIndexOutOfBoundsException("传递的索引超出了数组的适用范围"); |
| } else { |
| return array[index]; |
| } |
| } |
| } |
复制 | 抛出错误: |
| Exception in thread "main" java.lang.NullPointerException: 传入的数组为空 |
| at XXX.DemoThrow.getElement(DemoThrow.java:10) |
| at XXX.DemoThrow.main(DemoThrow.java:5) |
例子2
复制 | public class DemoThrow { |
| public static void main(String[] args) { |
| int[] array = {1, 2, 3}; |
| |
| int element = DemoThrow.getElement(array, 100); |
| } |
| |
| public static int getElement(int[] array, int index) { |
| if (array.length == 0) { |
| throw new NullPointerException("传入的数组为空"); |
| } else if (index == 0 || index > array.length - 1) { |
| throw new ArrayIndexOutOfBoundsException("传递的索引超出了数组的适用范围"); |
| } else { |
| return array[index]; |
| } |
| } |
| } |
复制 | 抛出错误: |
| Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 传递的索引超出了数组的适用范围 |
| at XXX.DemoThrow.getElement(DemoThrow.java:12) |
| at XXX.DemoThrow.main(DemoThrow.java:5) |
Objects非空判断requireNonNull
-
java.util.Objects类是由一些静态实用方法组成,这些方法是空指针安全的(即:容忍空指针的)
-
在源码中对对象null值进行了抛出异常错误,源码如下:
复制 | |
| public static <T> T requireNonNull(T obj) { |
| if (obj == null) |
| throw new NullPointerException(); |
| return obj; |
| } |
-
requireNonNull方法的使用
复制 | import java.util.Objects; |
| |
| public class DemoObjectsNonNull { |
| public static void main(String[] args) { |
| String s = null; |
| Objects.requireNonNull(s, "传入的参数为空"); |
| } |
| } |
复制 | 抛出错误: |
| Exception in thread "main" java.lang.NullPointerException: 传入的参数为空 |
| at java.util.Objects.requireNonNull(Objects.java:228) |
| at XXX.DemoObjectsNonNull.main(DemoObjectsNonNull.java:6) |
自定义非空判断
复制 | public class DemoObjectsNonNull { |
| public static void main(String[] args) { |
| String s = null; |
| methodNonNull(s); |
| } |
| |
| public static <E> void methodNonNull(E e) { |
| if (e == null) { |
| throw new NullPointerException("传入的参数为空"); |
| } |
| } |
| } |
复制 | 抛出错误: |
| Exception in thread "main" java.lang.NullPointerException: 传入的参数为空 |
| at XXX.DemoObjectsNonNull.methodNonNull(DemoObjectsNonNull.java:9) |
| at XXX.DemoObjectsNonNull.main(DemoObjectsNonNull.java:5) |
throws 关键字处理异常
throws作用
当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象。可以使用 throws关键字处理异常对象,它会把异常对象声明抛给方法的调用者处理(自己不处理,绐别人处理)最终交给JVM-->中断处理
使用格式
复制 | 修饰符 返回值类型 方法名(参数列表) throws AaaException, BbbException ... { |
| throw new AaaException("产生原因"); |
| throw new BbbException("产生原因"); |
| ... |
| } |
注意事项
- throws关键字必须写在方法声明处。
- throws关键字后边声明的异常必须是Exception或者是Exception的子类。
- 方法内部如果抛出了多个异常对象,那么throws后边必须也声明多个异常。如果批出的多个异常对象有子父类关系,那么直接声明父类异常即可
- 调用了一个声明抛出异常的方法,我们就必须处理声明的异常,要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM,要么try...catch自己处理异常。
举例
例子1:
复制 | import java.io.FileNotFoundException; |
| |
| public class Demo01Throws { |
| public static void main(String[] args) throws FileNotFoundException{ |
| String s = "/Users/data.txt"; |
| readFile(s); |
| } |
| |
| public static void readFile(String s) throws FileNotFoundException { |
| if ("/Users/data.txt".equals(s)) { |
| System.out.println("传入的参数是'/Users/data.txt'"); |
| } else { |
| throw new FileNotFoundException("传入的参数不是'/Users/data.txt'"); |
| } |
| } |
| } |
复制 | 输出结果: |
| 传入的参数是'/Users/data.txt' |
例子2:
复制 | import java.io.FileNotFoundException; |
| |
| public class Demo01Throws { |
| public static void main(String[] args) throws FileNotFoundException{ |
| String s = "/Users/data"; |
| readFile(s); |
| } |
| |
| public static void readFile(String s) throws FileNotFoundException { |
| if ("/Users/data.txt".equals(s)) { |
| System.out.println("传入的参数是'/Users/data.txt'"); |
| } else { |
| throw new FileNotFoundException("传入的参数不是'/Users/data.txt'"); |
| } |
| } |
| } |
复制 | 抛出错误: |
| Exception in thread "main" java.io.FileNotFoundException: 传入的参数不是'/Users/data.txt' |
| at XXX.Demo01Throws.readFile(Demo01Throws.java:11) |
| at XXX.Demo01Throws.main(Demo01Throws.java:6) |
try catch 关键字处理异常
使用格式
复制 | try { |
| ... |
| } catch (异常类名 变量名) { |
| ... |
| } |
| ... |
| catch(异常类名 变量名) { |
| ... |
| } ... |
注意事项
- try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象。
- 如果try中产生了异常,那么就会执行ctch中的异常处理逻辑,执行完catch中的处理逻辑,会继续执行try...catch之后的代码。
- 如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,执行完try中的代码,继续执行try...catch之后的代码。
举例
复制 | public class Demo01TryCatch { |
| public static void main(String[] args) { |
| |
| try { |
| String[] strings = {}; |
| System.out.println(strings[100]); |
| } catch (ArrayIndexOutOfBoundsException e) { |
| |
| System.out.println("Exception in thread \"main\" java.lang.ArrayIndexOutOfBoundsException"); |
| } catch (NullPointerException e) { |
| |
| System.out.println("Exception in thread \"main\" java.lang.NullPointerException"); |
| } |
| System.out.println("程序执行完成"); |
| } |
| } |
复制 | 输出结果: |
| Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException |
| 程序执行完成 |
Throwable类中3个异常处理的方法
复制 | public void printStackTrace() |
| |
| public String getMessage() |
| |
| public String toString() |
| |
这三个方法源码:
复制 | public void printStackTrace() { |
| printStackTrace(System.err); |
| } |
复制 | public String getMessage() { |
| return detailMessage; |
| } |
复制 | public String toString() { |
| String s = getClass().getName(); |
| String message = getLocalizedMessage(); |
| return (message != null) ? (s + ": " + message) : s; |
| } |
三个方法举例
复制 | public class DemoTryCatch { |
| public static void main(String[] args) { |
| try { |
| String[] strings = new String[10]; |
| getElement(strings, 10); |
| } catch (ArrayIndexOutOfBoundsException e) { |
| |
| System.out.println(e.getMessage()); |
| |
| System.out.println(e.toString()); |
| |
| e.printStackTrace(); |
| } |
| } |
| |
| public static String getElement(String[] array, int index) { |
| if (array.length == 0) { |
| throw new NullPointerException("传入的数组为空"); |
| } else if (index == 0 || index > array.length - 1) { |
| throw new ArrayIndexOutOfBoundsException("传递的索引超出了数组的适用范围"); |
| } else { |
| return array[index]; |
| } |
| } |
| } |
复制 | 控制台输出: |
| 传递的索引超出了数组的适用范围 |
| java.lang.ArrayIndexOutOfBoundsException: 传递的索引超出了数组的适用范围 |
| java.lang.ArrayIndexOutOfBoundsException: 传递的索引超出了数组的适用范围 |
| at XXX.DemoTryCatch.getElement(DemoTryCatch.java:19) |
| at XXX.DemoTryCatch.main(DemoTryCatch.java:5) |
finally代码块
格式
复制 | try { |
| ... |
| } catch (异常类名 变量名) { |
| ... |
| } |
| ... |
| catch(异常类名 变量名) { |
| ... |
| } finally { |
| ... |
| } |
注意事项
- finally不能单独使用,必须要和try一起使用
- finally一般用于资源释放(资源回收),无论程序是否出现异常,最后都要释放IO
举例
复制 | public class DemoFinally { |
| public static void main(String[] args) { |
| |
| try { |
| String[] strings = {}; |
| System.out.println(strings[100]); |
| } catch (ArrayIndexOutOfBoundsException e) { |
| |
| System.out.println(e.toString()); |
| } finally { |
| System.out.println("程序执行完成"); |
| } |
| |
| } |
| } |
复制 | 控制台输出: |
| java.lang.ArrayIndexOutOfBoundsException: 100 |
| 程序执行完成 |
多异常的捕获处理
多个异常分别处理
实例理解:
复制 | import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| public class Demo01ManyException { |
| public static void main(String[] args) { |
| |
| try { |
| int[] array = {1, 2, 3}; |
| int a = array[3]; |
| } |
| catch (ArrayIndexOutOfBoundsException e) { |
| System.out.println(e.toString()); |
| } |
| |
| |
| try { |
| List<Integer> list = new ArrayList<>(); |
| Collections.addAll(list, 1, 2, 3); |
| int b = list.get(3); |
| } |
| catch (IndexOutOfBoundsException e) { |
| System.out.println(e.toString()); |
| } |
| } |
| } |
复制 | 控制台输出: |
| java.lang.ArrayIndexOutOfBoundsException: 3 |
| java.lang.IndexOutOfBoundsException: Index: 3, Size: 3 |
多个异常一次捕获多次处理
实例理解:
复制 | import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| public class Demo01ManyException { |
| public static void main(String[] args) { |
| |
| try { |
| int[] array = {1, 2, 3}; |
| int a = array[3]; |
| |
| List<Integer> list = new ArrayList<>(); |
| Collections.addAll(list, 1, 2, 3); |
| int b = list.get(3); |
| } |
| catch (ArrayIndexOutOfBoundsException e) { |
| System.out.println(e.toString()); |
| } |
| catch (IndexOutOfBoundsException e) { |
| System.out.println(e.toString()); |
| } |
| |
| } |
| } |
复制 | 控制台输出: |
| java.lang.ArrayIndexOutOfBoundsException: 3 |
注意事项
一个try,多个catch,catch里面定义的异常变量,如果有子父类关系,那么子类的异常变量必须写在前面,否则会报错
如ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException:


多个异常一次捕获一次处理
实例理解:
复制 | import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| public class Demo01ManyException { |
| public static void main(String[] args) { |
| |
| try { |
| int[] array = {1, 2, 3}; |
| int a = array[3]; |
| |
| List<Integer> list = new ArrayList<>(); |
| Collections.addAll(list, 1, 2, 3); |
| int b = list.get(3); |
| } |
| catch (Exception e) { |
| System.out.println(e.toString()); |
| } |
| |
| } |
| } |
复制 | 控制台输出: |
| java.lang.ArrayIndexOutOfBoundsException: 3 |
finally有return语句
如果finally中有return语句,只会返回finally中的值。
如:
复制 | public class Demo01FinallyReturn { |
| public static void main(String[] args) { |
| System.out.println(Demo01FinallyReturn.method()); |
| } |
| |
| public static String method() { |
| try { |
| String s = "abc"; |
| return s; |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } finally { |
| String s = "ABC"; |
| return s; |
| } |
| } |
| } |
复制
子父类异常
- 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
- 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出。
如:
复制 | public class Fu { |
| |
| public static void method1() throws NullPointerException, ClassCastException { } |
| |
| public static void method2() throws IndexOutOfBoundsException { } |
| |
| public static void method3() { } |
| |
| public static void method4() { } |
| |
| } |
复制 | public class Zi extends Fu { |
| |
| |
| |
| |
| |
| |
| public static void method1() throws NullPointerException, ClassCastException { } |
| |
| |
| |
| |
| |
| public static void method2() throws ArrayIndexOutOfBoundsException { } |
| |
| |
| |
| |
| public static void method3() { } |
| |
| |
| |
| |
| |
| public static void method4(){ |
| try { |
| throw new Exception("编译期异常"); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| } |
自定义异常类的简单练习
要求
模拟注册操作,如果用户名已存在,则抛出异常并提示:亲,该用户名已经被注册。
分析
- 使用数组保存已经注册过的用户名
- 使用Scanner获取用户输入的注册的用户名
- 定义一个方法,对用户输入中的注册用户名进行判断,遍历存储已经注册过用户名的数组,获取每一个用户名,使用获取到的用户名和用户输入的用户名比较
实现
复制 | import java.util.Scanner; |
| |
| public class MyUsersException { |
| |
| private static String[] names = {"小红", "小明", "李华", "小军", "大雄"}; |
| |
| public static void registerUser(String scannerUser) { |
| for (String name : names) { |
| if (name.equals(scannerUser)) { |
| try { |
| throw new RuntimeException("亲,该用户名已被注册!"); |
| } catch (RuntimeException e) { |
| System.out.println(e.getMessage()); |
| return; |
| } |
| } |
| } |
| System.out.println("恭喜您注册成功!"); |
| } |
| |
| public static void main(String[] args) throws RuntimeException{ |
| Scanner scn = new Scanner(System.in); |
| System.out.print("输入要注册的用户名:"); |
| String registerUserName = scn.next(); |
| MyUsersException.registerUser(registerUserName); |
| } |
| } |
复制 | 控制台输入:李华 |
| 控制台输出: |
| 亲,该用户名已被注册! |
复制
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)