Java SEException(异常)
CAMELLIA!!! note 目录
异常
一、异常的概述
1.1 异常的概念&作用。
- 异常
(Exception)
是程序执行过程中出现的非正常情况,它们表示程序在运行时遇到了某种问题。
Java通过异常处理机制来处理这些问题,以保证程序的健壮性和可维护性。
1.2 异常的存在方式。
- 在Java中,异常以类的形式存在,通过继承
Throwable
类来定义。异常分为Error、Exception
两大类,其中Exception
又分为受检异常和非受检异常。
通过异常处理机制,Java程序可以捕获和处理运行时的错误,增强了程序的健壮性和可维护性。
- 当异常发生时,通常是通过创建异常类的对象(使用new关键字)来表示异常的情况。这些异常对象包含了异常的详细信息,例如错误消息和堆栈跟踪信息。
1.3 异常的继承结构
二、 Java中的异常机制
2.1 异常在程序中如何发生?
1 2 3 4 5 6 7 8
| @Test public void testException(){ NullPointerException npe = new NullPointerException(); throw npe; }
|
1 2 3 4
| public void testException(){ throw new ClassCastException(); }
|
2.2 自定义异常
自定义异常两步:
第一步:编写类继承RuntimeException或者Exception
第二步:提供两个构造方法,一个无参数,一个带有String参数的,并且在构造方法中调用super(String)
1 2 3 4 5 6
| public class IllegalNameException extends Exception{ public IllegalNameException(){} public IllegalNameException(String message){ super(message); } }
|
三、异常的处理
3.1 使用throws关键字声明异常以抛出
当方法可能抛出异常但不在方法内部处理,而是将其抛给调用者处理时,使用throws
关键字声明异常。这种方式适用于方法自身不适合处理异常,而是希望调用者决定如何处理。
方法本身不适合处理异常,而是将其抛给调用者处理。
希望调用者明确知道方法可能抛出的异常,并强制其处理。
示例代码:在这个方法中,需要让调用者知道发生异常(姓名,年龄不合规,自定义抛出异常。)
1 2 3 4 5 6 7 8 9 10
| public void save(String name, int age) throws IllegalNameException, IllegalAgeException{ System.out.println("用户["+name+"]的信息正在保存...."); if(name.length() < 6 || name.length() > 12){ throw new IllegalNameException(); } if(age < 18){ throw new IllegalAgeException(); } System.out.println("用户["+name+"]的信息保存成功!"); }
|
3.2 使用try-catch块捕获异常
try-catch
块是直接在方法内部捕获和处理异常的方式。
语法格式:
1 2 3 4 5 6 7 8
| try { }catch(异常类型1 变量名){ }catch(异常类型2 变量名){ } . . .
|
注意:
- catch语句可以看作是分支,try catch语句中,最多只有一个catch分支执行。
- catch可以写多个,但必须异常从小到大。
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class CustomExceptions { public static void main(String[] args){ Scanner scanner = new Scanner(System.in); System.out.println("欢迎使用本系统,先进行用户的注册:"); System.out.print("请输入用户名:"); String name = scanner.next(); System.out.print("请输入年龄:"); int age = scanner.nextInt();
UserService userService = new UserService();
try { userService.register(name, age); } catch (IllegalNameException e) { System.out.println("用户名不合法"); } catch (IllegalAgeException e) { System.out.println("年龄不合法"); } System.out.println("main over!"); } }
|
变量e存储的是对象地址
四、多异常捕获
在 Java 7 中,单个 catch 块可以捕获多种类型的异常,使用竖线 (|) 分隔。
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class CustomExceptions { public static void main(String[] args){ UserService userService = new UserService();
try { userService.register(name, age); } catch (IllegalNameException | IllegalAgeException e) { System.out.println("用户名或者年龄不合法"); } System.out.println("main over!"); } }
|
注意:多异常捕捉只有最后一个有变量,其余只写类型。
五、异常的常用方法。
5.1 getMessage()方法
getMessage()
方法是 Throwable
类(Exception
类和 Error
类的父类)中的一个方法,
用于获取创建异常对象时传递的详细消息。这个消息通常在异常被构造时作为参数传递给异常的构造方法。
这个消息有助于在捕获异常时了解导致异常的原因。
1 2 3 4 5 6 7 8 9
| package com.camellia.exception;
public class IllegalAgeException extends Exception{ public IllegalAgeException(){} public IllegalAgeException(String message){ super(message); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.camellia.exception;
public class UserServices { User user;
public UserServices() {}
public UserServices(User user) { this.user = user; }
public void register() throws IllegalNameException, IllegalAgeException { if(user.getName().length()>12||user.getName().length()<6) throw new IllegalNameException("无效名字异常,名字应在【6-12】位"); if(user.getAge()<0||user.getAge()>130) throw new IllegalAgeException("无效年龄异常,年龄应在【0-130】"); System.out.println(user.toString()); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.camellia.exception;
public class UserMain { public static void main(String[] args) { User user = new User("camellia",-10); UserServices userService = new UserServices(user); try { userService.register(); } catch (IllegalNameException e) { System.out.println("Illegal name: " + e.getMessage()); } catch (IllegalAgeException e) { System.out.println("Illegal age: " + e.getMessage()); } } }
|
5.2 printStackTrace方法
在 Java 中,printStackTrace
方法是 Throwable
类(Exception
类和Error
类的父类)的一部分,用于打印异常的堆栈跟踪信息。
堆栈跟踪显示了异常发生时调用堆栈中的方法调用顺序,帮助开发者了解异常的来源及其传播路径,适用于开发人员调试程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.camellia.exception;
public class UserMain { public static void main(String[] args) { User user = new User("c",10); UserServices userService = new UserServices(user); try { userService.register(); } catch (IllegalNameException e) { e.printStackTrace(); } catch (IllegalAgeException e) { System.out.println("Illegal age: " + e.getMessage()); } } }
|
六、finally语句块
finally
语句块是 Java 异常处理机制的一部分,用于确保某些代码在异常处理过程中始终被执行,不管是否发生异常。
它通常与try
和 catch
语句块一起使用(至少和try
一起),以保证在 try
语句块中进行的资源释放或清理操作一定会被执行。
6.1 用于资源释放
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import java.io.FileInputStream; import java.io.IOException;
public class FinallyResourceExample { public static void main(String[] args) { FileInputStream fis = null; try { fis = new FileInputStream("example.txt"); } catch (IOException e) { System.out.println("IOException caught: " + e); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { System.out.println("Error closing file: " + e); } } System.out.println("Finally block executed"); } } }
|
当然,只是开发中常用来关闭资源。
七、finally 块与 return 语句
如果try
或catch
块中有return
语句,finally
块仍然会在方法返回之前被执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class FinallyReturnExample { public static void main(String[] args) { System.out.println(methodWithFinally()); }
public static String methodWithFinally() { try { return "Return from try"; } finally { System.out.println("Finally block executed"); } System.out.println("但是这个代码不能执行了。"); } }
|
如果使用exit退出JVM,则finally代码无法执行
1 2 3 4 5 6 7 8 9 10 11
| public class FinallyWithExitExample { public static void main(String[] args) { try { System.out.println("Inside try block"); System.exit(0); } finally { System.out.println("Finally block executed"); } } }
|
在 Java 中,当一个 try 块中包含 return 语句,并且紧跟其后的 finally 块中也修改了返回的变量,最终返回的值会是 try 块中计算出的值,
而不是 finally 块中修改后的值。这是因为 return 语句会在 try 块中首先确定返回值,
然后在执行 finally 块中的代码,但 finally 块中的修改不会影响已经确定的返回值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class FinallyReturnExample { public static void main(String[] args) { System.out.println(methodWithFinally()); }
public static String methodWithFinally() { int i=100; try { return i; } finally { i++; } } }
|
注意:子类继承父类不能抛出更多的异常。