java:异常
异常体系–这些都是类
1)Throwable: 顶层类
2)Error: java虚拟机中无法解决的问题。Eg:资源耗尽、jvm内部错误、 StackOverflowError、OutOfMemoryError
3)Exception: 可通过代码处理的
分类:
1. 编译时异常/受检查异常 ----->Exception及其子类蓝色的部分
必须要显示处理(如果不显示处理,编译器会报错)
3. 运行时异常/非受检查异常 ----->RunTimeException以及其子类对应的异常,都称为运行时异常
异常的抛出 —将错误信息告知调用者
throw
1.用于方法的内部。
2.抛出的对象是Exception或是Exception的子类。
3.如果是RuntimeException或是RuntimeException的子类,不用处理,交给jvm。
4.出现编译时异常,必须显式处理才能通过编译。
5.异常抛出(一定是运行时抛出,编译过程不能抛异常),其后代码不会执行。
- 空指针异常
public static void array1 (int[] array) {
if(null == array) {
throw new NullPointerException("空指针异常");
//NullPointerException ex = new NullPointerException();
//throw ex;抛出的其实是一个异常类产生的对象
}
}
public static void main(String[] args) {
int[] arr = null;
array1(arr);
}
- 数组越界异常
public static void getElement(int[] array, int index) {
if(null == array) {
throw new NullPointerException("空指针异常");
}
if(index < 0 || index >= array.length) {
throw new ArrayIndexOutOfBoundsException("数组越界异常");
}
}
public static void main(String[] args) {
int[] array = {1,2,3};
getElement(array, 3);
}
- 算术异常
public static int calculate(int a, int b) {
int c = a / b;
if(b == 0) {
throw new ArithmeticException("算术异常");
}
return c;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
int b = scanner.nextInt();
int result = calculate(a,b);
System.out.println(result);
}
异常的捕获->异常的处理
1.异常的声明------throws关键字 声明扔处理
前面提到的throw关键字–出现编译时异常,必须处理才能通过编译
但现在用了throws关键字可以不用处理,可以交给方法调用者处理
1)跟在方法参数列表的后面
2)有多个需要声明的异常对象,用逗号隔开;
若存在父子关系,只写父类就行
3)声明的异常必须是Exception及Exception的子类
4)方法中声明这个异常之后,谁调用这个方法之后仍然要处理这个异常;
若调用者仍不处理,继续声明
public static void calculate1(int a, int b) throws ArithmeticException{
//声明之后未处理,交给了main
int c = a / b;
System.out.println(c);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = 10;
int b = 0;
try{
calculate1(a,b);
}catch (ArithmeticException e) {//捕获并处理
System.out.println("算术异常");
}
}
- 处理之前
- 处理之后
2.try-catch 捕获并处理
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
try{
// int[] arr = null;
// System.out.println(arr.length);
System.out.println(10/a); //若一旦出现了异常,try后面的代码将不会实现。
System.out.println("1234");
}catch (NullPointerException e) { //捕获异常
e.printStackTrace(); //打印异常的全部信息
System.out.println("处理空指针异常"); //处理异常
}catch (ArithmeticException e) {
e.printStackTrace();
System.out.println("处理算术异常");
}catch (Exception e) { //存在父子,父放在最后兜底
System.out.println("处理异常");
}finally { //一定会被执行,用来释放多余的资源
//finally不要有return
//若try和catch有return的话,会先执行finally的return,try里的return执行不了。
scanner.close();
System.out.println("释放资源");
}
System.out.println("其他代码"); //会被执行
}
异常处理的流程
执行try中的代码 -> try中出现异常 -> 与catch中的异常匹配 -> 匹配成功 -> 处理 -> finally
执行try中的代码 -> try中出现异常 -> 与catch中的异常匹配 -> 匹配不成功 -> throws给下个调用者 -> 一直throws到main函数都没成功 -> 交给jvm -> 终止程序
自定义异常
自己编写名字的异常类 extends Exception或者RuntimeException
private static String loginname = "zhangsan";//自己的用户名
private static String loginpassword = "12345678";//自己的密码
//声明自己写的异常类
public static void loginIsTrue(String name, String passWord) throws UserNameException, PassWordException {
if(!name.equals(loginname)) {
throw new UserNameException("用户名错误");//错误抛出UserNameException
}
if(!passWord.equals(loginpassword)) {
throw new PassWordException("密码错误");//错误抛出PassWordException
}
}
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
String name = scanner.next();//输入账号
String passWord = scanner.next();//输入密码
try {
loginIsTrue(name,passWord);//调用方法
}catch (UserNameException e) { //捕获UserNameException
System.out.println("已处理用户名异常");//处理
}catch (PassWordException e) {
System.out.println("已处理密码异常");
}finally{
scanner.close();
System.out.println("释放资源");
}
}
//自己写的异常类继承于Exception
public class PassWordException extends Exception{
public PassWordException() {//无参构造方法
}
public PassWordException(String message) {//有参构造方法
super(message);
}
}
//自己写的异常类继承于Exception
public class UserNameException extends Exception{
public UserNameException() {//无参构造方法
}
public UserNameException(String message) {//有参构造方法
super(message);
}
}