概念
异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将受影响。在程序中的意思就是:
异常:
指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。
异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行。
体系
解决异常两种方法
- 自己解决,程序可继续向下执行。自己解决步骤如下:
- 使用
try
块尝试着运行代码。如果出现异常,则进行第二步。 - 使用
catch
块对异常进行捕获,根据预先书写的代码对异常做出相应的决定。
- 使用
- 自己不做任何工作,一直抛出异常,将异常交给java虚拟机JVM处理,但如果交给他处理之后,程序就会中断。
样例一:自己解决
package main;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int y = 2;
int z = 0;
try {
int x = y / z;
System.out.println(x);
}catch (Exception e) {
// TODO: handle exception
System.out.println(e);
System.out.println("请重新输入除数:");
z = new Scanner(System.in).nextInt();
}
System.out.println("答案:" + 2 / z);
System.out.println("后面仍然可以运行哟");
}
}
运行结果:
java.lang.ArithmeticException: / by zero
后面仍然可以运行哟
样例二:交给java虚拟机JVM解决
package main;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int x = 2 / 0;
System.out.println(x);
System.out.println("后面仍然可以运行哟");
}
}
运行结果:
Exception in thread “main” java.lang.ArithmeticException: / by zero
at main.Main.main(Main.java:12)
finally代码块
该关键字,必须和 try-catch
代码块进行联合使用。
特点:
无论,try-catch
代码块做了什么内容,finally
代码块一定会执行,就算try-catch
代码块做了return
语句。仍然会执行finally
代码块。具体操作如下所示:
利用范围:
finally
代码块,经常用来做一些因为出现了异常,即将退出该程序的那一刻,进行一次资源释放操作。节约内存的消耗。
样例
package main;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int y = 2;
int z = 0;
try {
int x = y / z;
System.out.println(x);
}catch (Exception e) {
// TODO: handle exception
System.out.println(e);
System.out.println("请重新输入除数:");
z = new Scanner(System.in).nextInt();
return ;
}finally {
System.out.println("没想到吧,就算你return了我仍然会运行");
}
System.out.println("答案:" + 2 / z);
System.out.println("后面怎么不可以运行哟");
}
}
运行结果:
java.lang.ArithmeticException: / by zero
请重新输入除数:
2
没想到吧,就算你return了我仍然会运行
注意事项
- 多个异常分别处理。
- 多个异常一次捕获,多个处理。
- 多个异常一次捕获,一个处理。
样例
package main;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 1. 多个异常分别处理
try {
int[] arr = { 1, 2, 3 };
System.out.println(arr[3]);// ArrayIndexOutOfBoundsException: 3
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e);
}
try {
ArrayList<Integer> list = new ArrayList();
list.add(0);
list.add(1);
list.add(2);
System.out.println(list.get(3));// IndexOutOfBoundsException: Index: 3, Size: 3
} catch (IndexOutOfBoundsException e) {
System.out.println(e);
}
System.out.println("==========================");
// 2. 多个异常一次捕获,多个处理。
// 由于只能捕获一次。后面的异常便会出现执行不到的情况
try {
int[] arr = { 1, 2, 3 };
System.out.println(arr[3]);// ArrayIndexOutOfBoundsException: 3
ArrayList<Integer> list = new ArrayList();
list.add(0);
list.add(1);
list.add(2);
System.out.println(list.get(3));// IndexOutOfBoundsException: Index: 3, Size: 3
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e);
} catch (IndexOutOfBoundsException e) {
System.out.println(e);
}
System.out.println("=====================================");
// 3. 多个异常一次捕获,一个处理。
// 在处理过程中。异常的继承关系。如果是该的父类,那么完全OK
// 换句话说,相当于越接近异常超类Exception,那么包含的异常就越多。
// 通常情况下,如果我们记不住这么多异常,我们就只写超类Exception即可
try {
int[] arr = { 1, 2, 3 };
System.out.println(arr[3]);// ArrayIndexOutOfBoundsException: 3
ArrayList<Integer> list = new ArrayList();
list.add(0);
list.add(1);
list.add(2);
System.out.println(list.get(3));// IndexOutOfBoundsException: Index: 3, Size: 3
} catch (IndexOutOfBoundsException e) {
System.out.println(e);
}
}
}
运行结果
java.lang.ArrayIndexOutOfBoundsException: 3
java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
==========================
java.lang.ArrayIndexOutOfBoundsException: 3
=====================================
java.lang.ArrayIndexOutOfBoundsException: 3
异常扩展—自定义异常类
产生原因: 由于系统提供的异常类可能并不能满足我们的需求(给出的异常提示要做到看到这个提示我就知道是由于什么操作导致程序产生了异常),这个时候就要自己创建一个异常类,进行捕获,声明,抛出。
步骤
- 自定义一个异常类,类名形如:XxxException
- 继承Exception类
- 书写带参构造方法和无参构造方法
- 带参格式:类名(String x){ super(x) ; }
- 无参格式:类名(){ super() ;}
样例
package main;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 注册账户。不能出现相同的用户名
ArrayList<String> username = new ArrayList<String>();
username.add("张三");
try {
String name = new Scanner(System.in).next();
if(username.contains(name)) {
throw new RigisterException();
}
}catch (Exception e) {
// TODO: handle exception
System.out.println("出现用户名相同:"+ e );
}
}
}
// 自定义异常类
class RigisterException extends Exception{
public RigisterException() {
// TODO Auto-generated constructor stub
super();
}
public RigisterException(String x) {
// TODO Auto-generated constructor stub
super(x);
}
}
运行结果:
张三
出现用户名相同:main.RigisterException
扩展知识
打印异常信息的时候。可以根据自己的需求,打印我只需要获得异常多少信息。
返回值 | 方法 | 解释 |
---|---|---|
String | getMessage() | 返回此throwable的详细消息字符串 |
String | toString() | 返回此可抛出的简短描述 |
void | printStackTrace() | 将此throwable和其追溯打印到标准错误流 |
样例
package main;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try {
int x = 2 / 0;
System.out.println(x);
}catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
// 这里强调,打印 e 默认 调用了 tostring 方法
System.out.println(e.toString());
System.out.println(e);
e.printStackTrace();
}
System.out.println("后面可以继续代码编写");
}
}
运行结果:
/ by zero
java.lang.ArithmeticException: / by zero
java.lang.ArithmeticException: / by zero
java.lang.ArithmeticException: / by zero
at main.Main.main(Main.java:7)
后面可以继续代码编写