文章目录
1、Java异常的定义
- java程序执行过程中出现的错误,异常出现以后会导致下面代码不执行
2、 异常的分类
2.1、如何区分运行时异常和检查时异常
2.1.1、运行时异常
- 直接或间接的继承RuntimeException。也就是这个异常的父类是RuntimeException或者父类的父类是RuntimeException等情况。
- 不需要显示处理。也就是这个异常不会报错,可以被编译,比如代码
System.out.println(1/0);
这是不会报错的,可以被编译,但是是一个异常。
2.1.2、检查时异常
- 需要显示处理比如代码
Class.forName("java.lang.Object");
代码块虽然没有错误,但是系统会报错
我们必须手动的去解决这个问题,系统会提示有两种方法可以解决这个异常,这就是检查时异常
例:我们这里选择第二种问题就可以解决了。
3、自定义异常类
public class Student {
private int age;
public void SetAge(int age) {
if(age<0||age>15) {
System.out.println("年龄范围:大于0岁,小于15岁");
}else {
this.age=age;
}
}
public int GetAge() {
return age;
}
}
import com.jd.vo.Student;
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.SetAge(12000);
System.out.println(student.GetAge());
}
}
单纯的输出提示无法定位到底程序哪个地方出现了问题 throw 异常对象,这样写会导致写Test类的人造成困扰,不知道错误源在哪里,只知道错了。不知道为什么。所以我们需要使用抛出异常(thorw)。比如将以上代码稍微改改:
public class Student {
private int age;
public void SetAge(int age) {
if(age<0||age>15) {
//System.out.println("年龄范围:大于0岁,小于15岁");
throw new NullPointerException("年龄范围:大于0岁,小于15岁");
}else {
this.age=age;
}
}
public int GetAge() {
return age;
}
}
这里抛出的异常是空指针异常,但是异常并不是空指针异常,就出现了词不达意,不能见名知义,也没有现成的异常可以表达这个异常,所以就需要自定义异常,更好的阐述这个异常。
- 方法:自定义一个异常类,该类继承某个已有的异常类即可。
代码如下:
public class AgeException extends RuntimeException{
public AgeException(String massage) {
super(massage);
}
}
这样以后,我们再去执行Test类中的代码,就会很好的显示我们需要的异常类型。
- 注意
- 如果将自定义异常类继承的是检查时异常类,则该自定义异常类为检查时异常类,则如果继承运行时异常,则该自定义异常为运行时异常。
- 如果throw抛出的是由运行时异常创建的对象,则不需要显式使用throws;否则需要显式使用throws或者直接try-catch-finally
-
解决方法
-
方法一 thorws
public class AgeException extends Exception{
public AgeException(String massage) {
super(massage);
}
}
如果自定义异常类是继承的Exception,则Student类必须这样写:
public class Student {
private int age;
public void SetAge(int age) throws AgeException{
if(age<0||age>15) {
throw new AgeException("年龄范围:大于0岁,小于15岁");
}else {
this.age=age;
}
}
public int GetAge() {
return age;
}
}
Test类也需要throws AgeException:
public class Test {
public static void main(String[] args) throws AgeException{
Student student = new Student();
student.SetAge(12000);
System.out.println(student.GetAge());
}
}
- 方法二 try-catch-finally
public class Student {
private int age;
public void SetAge(int age){
if(age<0||age>15) {
try {
throw new AgeException("年龄范围:大于0岁,小于15岁");
}catch(AgeException e) {
e.printStackTrace();
}
}else {
this.age=age;
}
}
public int GetAge() {
return age;
}
}
4、异常的处理方式
4.1、try-catch-finally
- try用于检查无论是否出现异常;如果有异常则进入catch语句块。
- catch语句块用来捕获错误。
- finally 语句块无论是否出现异常都会执行。
public class Test2 {
//异常异常方式:try-catch-finally:throw与throws
public static void main(String[] args) {
//try-catch-finally
//1、try用于检查无论是否出现异常;如果有异常则进入catch语句块
//2、finally 语句块无论是否出现异常都会执行
//3、一个try可以有多个catch分支,就近原则;注意:必须从小到大
int age = 12;
try {
System.out.println(1/0);
}catch(ArithmeticException e) {
System.out.println(e);
}finally {
System.out.println("无论异不异常都执行");
}
System.out.println(age);
}
}
这个异常其实是一个对象,就将这个异常赋给e保存起来。
执行结果如下:
4.1.1、一个try可以有多个catch分支,就近原则;注意:必须从小到大
比如代码
try {
System.out.println(1/0);
}catch(ArithmeticException e) {
System.out.println(e);
}catch(NullPointerException e) {
System.out.println(e);
}catch(RuntimeException e) {
System.out.println(e);
}catch(Exception e) {
System.out.println("aaaaaaaaaaaa"+e);
}finally {
System.out.println("无论异不异常都执行");
}
如果是这个错误,catch分支就会执行第一个分支。
try {
//System.out.println(1/0);
String str = null;
System.out.println(str.length());
}catch(ArithmeticException e) {
System.out.println(e);
}catch(NullPointerException e) {
System.out.println(e);
}catch(RuntimeException e) {
System.out.println(e);
}catch(Exception e) {
System.out.println("aaaaaaaaaaaa"+e);
}finally {
System.out.println("无论异不异常都执行");
}
如果是空指针错误就会走第二个catch分支。
try {
// System.out.println(1/0);
// String str = null;
// System.out.println(str.length());
Class.forName("asdafasf");
}catch(ArithmeticException e) {
System.out.println(e);
}catch(NullPointerException e) {
System.out.println(e);
}catch(RuntimeException e) {
System.out.println(e);
}catch(Exception e) {
System.out.println("aaaaaaaaaaaa"+e);
}finally {
System.out.println("无论异不异常都执行");
}
如果找不出错误就会执行第四个分支。因为Exception是所有异常的父类。
4.2、throw与throws
区别:
- throw : 异常类创建的对象 方法内或代码块内
- throws : 异常类 方法参数列表括号的后面
如果是RuntimeException(运行时异常)就不会报错,如果是Excetion(检查时异常),上面代码块,是会报错的,需要throws或者try-catch-finally,但是throws只能放在方法参数列表括号的后面,所以就是只能try-catch-finally:
public class Test2 {
{
int a = 1;
int b = 0;
if(b==0) {
try {
throw new Exception("分母不能为0");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(a/b);
}
public static void main(String[] args) {
new Test2();
}
}
- 小注意throws后面不能直接跟代码
4.3、两种异常处理的区别
注意绿色标注的地方,我们可以发现当使用throws抛出异常时,后面代码就不执行了,而使用try-catch-finally的时候,后面的代码还是可以得以执行。
我们来小小理解一下以下代码: