异常就是程序出现了不正常的情况。
程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
Java有一套独立的异常处理机制,在遇到异常时,程序会抛出一个封装了错误信息的异常对象。
Exception分为编译时异常和运行时异常(RuntimeException)
最顶层为Throwable
Throwable下有Error 和 Exception
编译时异常
直接继承Exception,也叫检查时异常
在编译时期就必须处理,否则编译失败,程序无法运行。
(如日期格式化异常ParseException)
运行时异常
继承自RuntimeException的异常。
编译期间无需处理,可以通过优化代码逻辑来解决。
(如空指针异常,数组索引越界,类型转换异常等)
1.一旦出现异常,try{}里面的代码将停止执行,跳转到对应的catch{}块里的代码继续执行
2.catch执行结束后,会继续执行catch后面的代码。
好处:代码出错后可以继续往后执行。
public static void main(String[] args) {
try {
int i = 1/0;
int[] arr = new int[0];
System.out.println(arr[0]);
int arr2[] = null;
System.out.println(arr2.length);
}catch (NullPointerException e){
System.out.println("空指针异常:"+e);
}
catch (ArrayIndexOutOfBoundsException e){
System.out.println("数组越界:"+e);
}
catch (Exception e) {//未知异常,可以直接使用Exception,要用此异常必须写最后面
e.printStackTrace();//将详细信息打印
}
System.out.println("后续代码");
}
//键盘录入一个年龄,如果录入的不是整数,要求重新录入
public static void main(String[] args) {
while (true) {
try {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的年龄:");
int age = scanner.nextInt();
System.out.println(age);
break;
} catch (Exception e) {
System.out.println("你输入的年龄有误,请重新输入:");
}
}
}
因为异常会引发程序跳转,导致某些语句执行不到,而有一些特定的代码无论异常是否发生都需要执行。
finally代码块就可以解决这个问题,在finally代码块中的代码一定会被执行。
不管是否发生异常,finally代码块都会被执行。
因此可以在finally代码块中执行关闭连接、关闭文件和释放线程锁的操作。
public static void main(String[] args) {
try {
System.out.println("1");
return;
} catch (Exception e) {
System.out.println("2");
}finally {
System.out.println("3");
}
System.out.println("4");
//输出1、3(finally代码块中一定会执行)
}
当一个方法内部产生异常,而方法无法做处理时,可以在该方法的头部声明这个异常,把异常交给调用者进行处理。
throws关键字可以声明抛出多个异常,多个异常使用逗号隔开
throws可以在自定义方法上,抛出异常,谁调用方法谁处理异常。
抛出的编译异常,调用者一定要处理。
抛出的运行时异常,调用者可处理或不处理。
(实际开发中,运行异常通常是修复代码去解决,而不是使用异常处理解决)
class Person {
public void eat() throws Exception{
System.out.println("父类方法");
}
}
//子类重写的方法,抛出的异常要小于或等于父类
//实际开发中,父类抛什么异常,子类跟着一样就行
class Student extends Person {
@Override
public void eat() throws Exception{
System.out.println("子类方法");
}
}
子类重写的方法,抛出的异常要小于或等于父类
实际开发中,父类抛什么异常,子类跟着一样就行
/*
在方法中,使用throw制造异常,让方法停止
throw和return都可以让方法结束
*/
public static void main(String[] args) {
setAge(8);
}
public static void setAge(int age){
if(age>=18){
System.out.println("年龄合法,允许访问");
}else{
//产生异常,告知调用者 new的是运行时异常可以不做处理
//new的是编译异常,需要在方法定义上使用thows进行处理
throw new RuntimeException("年龄不合法,拒绝访问");
}
}
throws
是异常的处理方式之一,在方法定义使进行声明
表示声明异常,告知调用着,该方法可能会出现这样的异常,需要调用者自行处理
throw
是产生一个异常的关键字,用在方法体内部
表示创建并抛出一个异常对象,throw与return有一样的效果,执行了throw之后,方法调用会结束
JDK提供的异常虽然比较多,但是不一定符合我们的需求
此时我们可以根据自己的业务来定义异常类。例如年龄负数等
步骤:
1.定义异常类
2.写继承关系
3.空参构造
4.带参构造
public class JwlException extends Exception{
public JwlException() {
}
public JwlException(String message) {
super(message);
}
}
public static void main(String[] args) {
try {
setAge(15);
} catch (JwlException e) {
e.printStackTrace();
}
}
public static void setAge(int age) throws JwlException{
if(age>=18){
System.out.println("年龄合法,允许访问");
}else{
//产生异常,告知调用者
throw new JwlException("年龄不合法,拒绝访问");
}
}
自定义异常存在的意义:
就是为了让控制台的报错信息更加的见名知意。
如果你对本文有疑问,你可以在文章下方对我留言,敬请指正,对于每个留言我都会认真查看。