【Java】如何理解Java中的异常机制?
1 异常的概念
2 异常的分类
3 异常的产生过程
4 处理异常的方式
4.1 throw关键字
作用:在指定方法中抛出指定异常
使用格式:throw new xxxException(“异常产生原因”)
注意事项:
- 必须写在方法内部
- new的对象要是Exception 或 Exception的子类
- 如果抛出指定的异常对象,必须处理这个异常对象。
- 如果创建的时RuntimeException或其子类,默认交给JVM处理(打印异常对象,中断程序)
- 如果创建的时编译异常,就必须处理这个异常,必须throws或者try-catch
小贴士:必须首先对方法传递来的参数进行合法性校验,如果参数不合法,必须抛出异常,告知方法调用者,传递的参数有问题。
示例
运行时异常:NullPointerException
4.2 Objects非空判断
Objects类的静态方法
public static <T> T requireNonNull(T obj) {if (obj == null)throw new NullPointerException() ;return obj; }简化非空判断
public static void main(String[] args) {method(null);}public static void method(Object obj){Objects.requireNonNull(obj,"传递对象为空");}4.3 throws声明异常
异常处理的第一种方式,交给别人处理
作用:当方法内部抛出异常对象时,必须处理异常对象,可以使用throws关键字处理,会把异常对象抛给方法调用者处理,自己不处理,交给他人处理,最终交给JVM处理。(JVM中断处理)
使用方式:在方法声明时使用
注意:
- 必须写在方法声明处
- 必须是Exception或其子类
- 抛出多个异常,声明处要声明多个异常,如果是父子异常,声明父异常即可
- 调用了声明异常的方法必须处理声明的异常。throws抛出最终交给JVM处理或者try-catch定义异常处理逻辑。
编译时异常:FileNotFoundException
public static void main(String[] args) throws FileNotFoundException {method("c:\\d.txt");}public static void method(String filename) throws FileNotFoundException {if(!filename.equals("c:\\\\a.txt")){throw new FileNotFoundException("文件路径错误");}}FileNotFoundException extends IOException extends Exception
public static void main(String[] args) throws IOException {readFile("c:\\a.doc");}public static void readFile(String filename) throws IOException {if(!filename.endsWith(".txt")){throw new IOException("文件后缀不对");}}4.4 try-catch捕获异常
异常处理的第二种方式,自己处理,程序不中断
public static void main(String[] args) throws IOException {try{readFile("d:\\a.tx");}catch (IOException e){System.out.println("文件后缀有误");}System.out.println("程序不中断,后续代码继续执行");}public static void readFile(String filename) throws IOException{if(!filename.endsWith(".txt")){throw new IOException("文件后缀有误");}System.out.println("读取文件");}4.5 Throwable类中三个异常处理方法
- String getMessage()
打印Message: throw new IOException(Message);
public static void main(String[] args) {try{readFile("d:\\a.tx");}catch (IOException e){System.out.println(e.getMessage());}System.out.println("程序不中断,后续代码继续执行");}public static void readFile(String filename) throws IOException{if(!filename.endsWith(".txt")){throw new IOException("文件后缀有误");}System.out.println("读取文件");}- String toString()
重写Object类的toString
public static void main(String[] args){try{readFile("d:\\a.tx");}catch (IOException e){System.out.println(e.toString());}System.out.println("程序不中断,后续代码继续执行");}public static void readFile(String filename) throws IOException{if(!filename.endsWith(".txt")){throw new IOException("文件后缀有误");}System.out.println("读取文件");}- void printStackTrace()
4.6 finally代码块
public static void main(String[] args){try {readFile("d:\\a.tx");} catch (IOException e) {e.printStackTrace();} finally {System.out.println("异常出现后依旧需要执行的代码");}System.out.println("程序不中断,后续代码继续执行");}public static void readFile(String filename) throws IOException{if(!filename.endsWith(".txt")){throw new IOException("文件后缀有误");}System.out.println("读取文件");}4.7 多异常捕获
分别捕获,分别处理
public static void main(String[] args) {int[] arr = {1,2,3};List<Integer> list = new ArrayList<>();list.add(1);try{System.out.println(arr[3]);}catch (ArrayIndexOutOfBoundsException e){e.printStackTrace();}try{System.out.println(list.get(1));}catch (IndexOutOfBoundsException e){e.printStackTrace();}System.out.println("后续代码继续执行...");}一次捕获,多次处理
public static void main(String[] args) {try{int[] arr = {1,2,3};List<Integer> list = new ArrayList<>();System.out.println(arr[3]);list.add(1);System.out.println(list.get(1));}catch (ArrayIndexOutOfBoundsException e){e.printStackTrace();}catch (IndexOutOfBoundsException e){e.printStackTrace();}System.out.println("后续代码继续执行...");}
注意事项:一个try多个catch,catch中的异常变量如果有父子关系,子类异常变量必须写在上面,否则会报错。(XXXException has already been caught)
一次捕获,一次处理
public static void main(String[] args) {try {int[] arr = {1, 2, 3};List<Integer> list = new ArrayList<>();System.out.println(arr[3]);list.add(1);System.out.println(list.get(1));}catch (Exception e){e.printStackTrace();}System.out.println("后续代码继续执行...");}运行时异常被抛出可以不处理。即不捕获也不声明抛出。
如果finally有return语句,永远返回finally中的结果,避免该情况。
如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理【try-catch】,不能声明抛出。
5 自定义异常
- 自定义异常类一部都是以Exception结尾
- 必须继承Exception(编译期异常,要么try-catch要么throws)或者继承RuntimeException(运行期异常交给JVM中断处理)
模拟注册操作
throws
public class Register {static String[] usernames = {"张三","李四","王五"};public static void main(String[] args) throws RegisterException {System.out.print("请输入待注册用户名:");Scanner sc = new Scanner(System.in);String username = sc.next();checkUserName(username);System.out.println("恭喜,注册成功!");}//继承Exception是编译期异常 throws 处理public static void checkUserName(String name) throws RegisterException {for(String n: usernames){if(n.equals(name)){throw new RegisterException("该用户名已注册");}}} }try-catch
public class Register {static String[] usernames = {"张三", "李四", "王五"};public static void main(String[] args) {System.out.print("请输入待注册用户名:");Scanner sc = new Scanner(System.in);String username = sc.next();try {checkUserName(username);} catch (RegisterException e) {e.printStackTrace();return;}System.out.println("恭喜,注册成功!");}//继承Exception是编译期异常 throws 处理public static void checkUserName(String name) throws RegisterException {for(String n: usernames){if(n.equals(name)){throw new RegisterException("该用户名已注册");}}} }总结
以上是生活随笔为你收集整理的【Java】如何理解Java中的异常机制?的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: Android官方开发文档Trainin
- 下一篇: 【Java】关于Java中的各种流