1.先通过一张图片了解一下有什么异常
在Java中,
Throwable
是所有可抛出对象的超类。它有两个主要的子类:Error
和Exception
,它们都直接继承自Throwable
。
-
Error是指编译器不能处理的错误,需要程序员手动去解决,表示严重的问题,通常由于系统故障或虚拟机自身的问题引起,如内存不足(OutOfMemoryError)、栈溢出(StackOverflowError)等
-
Exception是指可以通过代码来解决的异常,它的子类分为受查异常和非受查异常(RuntimeException)
-
受查异常:指需要通过try-catch或者throws来声明的异常
-
非受查异常:不需要以上操作
2.处理异常的5个关键字
throw try catch finally throws
2.1 throw 与 throws
(这里即使不使用 try-catch 也同样可以执行 )
如果抛出的是受查异常,也就是除了RuntimeException 之外的异常,就需要throws来声明
第一个throws是声明
第二个throw是抛出异常
在方法体内声明抛出一个异常,这样调用这个方法的任何代码都必须捕获这个异常
1中我们可以看到抛出异常的同时后续代码不会执行
2中看到捕获异常之后执行接下来代码,并用printStackTrace来答应 异常的堆栈跟踪信息
3中打印出参数中的字符串
注意:
1.throw必须写在方法体内部
2.抛出的是RuntimeException或者它的子类,可以不用处理
3.如果不是则需要处理,否则无法通过编译
4.异常一旦抛出,其后的代码不会执行
2.2 try-catch
通常是这样的
try{
要执行的代码
}catch(异常类型){
.......
}
catch (ArrayIndexOutOfBoundsException e)
也可以这样写
catch (NullPointerException | ArrayIndexOutOfBoundsException e)
但是不推荐,这样不知道捕获的是那个异常
写两个catch,但是其中一个捕获到下一个不会捕获
public static void main(String[] args) {
int[] array = {1,2,3};
try{
System.out.println(array[55]);
array = null;
System.out.println(array[0]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常。。。");
}
catch (NullPointerException e){
System.out.println("空指针异常。。。");
}
System.out.println("after");
}
可以修改成这样
public static void main(String[] args) {
int[] array = {1,2,3};
try{
System.out.println(array[55]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常。。。");
}try{
array = null;
System.out.println(array[0]);
}
catch (NullPointerException e){
System.out.println("空指针异常。。。");
}
System.out.println("after");
}
有不知道的异常类型可以用Exception来兜底,前提是Exception在后,也就是父类在后
catch (ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常。。。");
}
catch (Exception e){
System.out.println("异常。。。");
}
注意:
1.try块内抛出异常位置之后的代码不会执行
2.有多个异常类型与catch中捕获类型不匹配的,不被捕获会继续往外抛,直到JVM收到中断程序
3.try中抛出多个不同异常对象,必须使用多个catch来捕获,而异常之间如果具有父子关系,需要子类在前,父类在后
2.3 finally
上面说到throw抛出异常之后并不会执行接下来的代码
finally可以在抛出异常之后继续执行
那它的作用是什么呢
public static int func() {
Scanner scanner = null;
try{
scanner = new Scanner(System.in);
int data = scanner.nextInt();
return data;
}catch (InputMismatchException I){
I.printStackTrace();
}finally {
System.out.println("finally 中的代码。。。");
scanner.close();
}
return 0;
}
public static void main(String[] args) {
func();
}
可以关闭没有关闭的程序,防止浪费
finally {
System.out.println("finally 中的代码。。。");
scanner.close();
}
3.处理流程
1.先执行try中代码
2.如果try中的代码出现异常,就会结束try中的代码
3.此时catch中的异常类型匹配的话就会执行catch中的代码
4.如果没有的话就会向上传递到上层调用者
5.一直到main方法还没有处理异常,就会交给JVM处理,此时程序就会异常终止
6.无论如何会执行finally的代码
4.自定义异常
创建一个类型继承想继承的异常,并创建继承类型的方法
public class UserNameException extends RuntimeException{
public UserNameException() {
super();
}
public UserNameException(String message) {
super(message);
}
}
这里写了一个登录系统,当用户名和密码不正确的时候会抛出异常
class User{
private String UserName;
private int UserPassword;
public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
public int getUserPassword() {
return UserPassword;
}
public void setUserPassword(int userPassword) {
UserPassword = userPassword;
}
public void login(String name, int password){
if(!UserName.equals(name)){
throw new UserNameException("用户名错误。。。");
}
if (UserPassword != password ){
throw new UserPasswordException("密码错误。。。");
}
System.out.println("登录成功!");
}
}
public class login {
public static void main(String[] args) {
User user = new User();
user.setUserName("zack");
user.setUserPassword(666);
try{
user.login("zack",666);
}catch (UserNameException e){
e.printStackTrace();
}catch (UserPasswordException e){
e.printStackTrace();
}
}
}