异常
程序在运行时出现错误通知调用者的一种机制。
Throwable类是Java语言中所有错误和异常的父类。
异常分为以下两种:
1.运行时异常/非受查异常:在程序运行时抛出的异常
eg:
public static void main(String[] args) {
int[] array = {1, 2, 3, 4};
System.out.println(array[4]);
System.out.println("hello");
}
运行结果
一些常见的非受查异常:
运算异常
空指针异常
数组下标越界异常
Java中处理异常的方式
try{
//可能出现异常的代码块
}catch(异常的类型 命名){
//捕获try当中可能出现的异常
}catch(异常的类型 命名){
//捕获try当中可能出现的异常
}finally{
}
eg:
public static void main1(String[] args) {
int[] array = {1, 23, 4, 5};
try {
System.out.println(array[4]);
}catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
System.out.println("捕获到了数组越界异常");
}
System.out.println("hello");
}
运行结果
可以看到,当程序抛出异常时,使用catch块进行捕获,程序自己来处理这个异常,这样的结果是,后续的程序会继续执行,如果不使用try/catch捕获异常,那么这个异常将直接交给JVM处理,程序会立即终止,不会执行后续代码。
异常处理的流程
1.程序先执行try中的代码。
2.如果try中的代码出现异常,就会结束try中的代码,看和catch中的异常类型是否匹配。
3.如果找到匹配的异常类型,就会执行对应的catch中的语句。
4.如果没有找到匹配的异常类型,就会将异常向上传递到上层调用者。
5.无论是否找到匹配的异常类型,finally中的代码都会被执行(在该方法结束前执行)。
6.如果上层调用者也没有处理的了异常,就继续向上传递。
7.一直到main方法也没有合适的代码处理异常,就会交给JVM来进行处理,此时程序就会异常终止。用try
catch处理异常需要注意的问题:
1.catch块中,一定要捕获相应的异常(比如说不能用ArrayIndexOutOfBoundException去捕获空指针异常),如果程序抛出的异常在catch块当中不能被捕获,那么就会交给JVM处理。
2.可以通过catch来捕获多个异常。
3.不建议直接捕获Exception异常,这样无法分析具体是什么异常。。4.finally块当中的代码终究会被执行。
5.不建议在finally当中出现return语句,因为finally语句是一定会被执行的。
public static void func(){
int[] array={1,2,3,4};
System.out.println(array[100]);
}
public static void main(String[] args) {
/*func();*/
try{
func();
}catch (ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}
System.out.println("after try catch");
}
//方法的调用是要到栈上开辟内存的,如果本方法中没有合适的处理异常的方式,
//就会沿着调用栈向上传递
// func函数中没有处理异常的方式,那么调用这个方法的main函数就必须处理,
// 如果main函数中没有异常处理,那么就会交给JVM,那么程序必然会异常中断
抛出异常
关键字: throw
一般是用来抛出某个你想抛出的异常(也可以是自定义的异常)
异常声明
public static int divide(int x, int y) throws ArithmeticException{//throws关键字可以声明异常
if (y == 0) {
throw new ArithmeticException("y==0");
}
return x / y;
}
//抛出异常 throw 一般是用来抛出某个你想抛出的异常(也可以是自定义的异常)
public static void main(String[] args) {
try {
int ret=divide(20, 0);
System.out.println(ret);
}catch (ArithmeticException e){
e.printStackTrace();
System.out.println("异常");
}finally {
System.out.println("继续执行!");
}
2.编译时异常/受查异常:在程序编译时的异常
受查异常在编译之前就必须处理掉,不然无法通过编译。
这里的CloneNotSupportedException就是一个受查异常。
用try/catch将其包裹,就可以处理这个首查异常,此时可以编译通过。
3.自定义异常
自定义异常最好继承于Exception,这样的好处是他必须去处理这个异常。
class UserException extends Exception {//自定义一个用户名异常继承于Exception
public UserException(String message) {//构造方法
super(message);
}
}
class PasswordException extends Exception {//自定义一个密码异常继承于Exception
public PasswordException(String message) {//构造方法
super(message);
}
}
class Text {
static String userName = "lee";
static String password = "123456";
}
public class TestDemo3 {
public static void main(String[] args) {
try {
login("lee", "123456");
} catch (UserException e) {
e.printStackTrace();
} catch (PasswordException e) {
e.printStackTrace();
}
}
public static void login(String userName, String password) throws UserException, PasswordException {//自定义login方法并声明用户名异常和密码异常
if (!Text.userName.equals(userName)) {
throw new UserException("用户名异常");
}
if (!Text.password.equals(password)) {
throw new PasswordException("密码异常");
}
System.out.println("登陆成功!");
}
}