Exception
当我们在运行程序的时候,经常会遇见系统报错,其实系统在下面打印出来的是一个异常类的返回值和异常的文件夹和位置
异常类的父类是Throwable,子类有Error和Exception.
其中Error的异常是系统崩溃或者数据库崩溃导致的,Exception的异常是有程序代码的异常导致的
Exception的有很多子类我们常见的有三类:空指针(NullPointerException),
数组下标越界(ArrayIndexOutOfBoundsException)和算数异常(ArithmeticException)
那么当异常出现的时候,怎么处理呢?
其实main方法会自己尝试着去解决,如果解决不了就会把问题抛给上一级,也就是jvm(java虚拟机)去解决,
jvm所做出的操作就是打印出错误的信息和错误出现的文件夹和位置,并结束程序
下面我们来看一下例子:
String[] array = {"我错了"};
//在访问array[1]的时候出现了数组下标越界,这时候系统的内部会生成一个异常类的对象
//相当于生成ArrayIndexOutOfBoundsException e = new ArrayIndexOutOfBoundsException();
//这时候异常就抛给了虚拟机去处理,虚拟机就打印出错误信息和错误信息的位置,并结束掉程序
System.out.println(array[1]);
当异常发生的时候,一般有两种方式去解决异常
1.抛给系统解决:其实就是让jvm打印出错误并结束程序
2.我们自己解决异常:我们解决的方法就是使用 try … catch …; 在try中放入可能错误的代码语句,在catch中放入捕获到错误后要执行的语句.
try{ }是测试异常
catch{}是捕获异常
下面我们还是以上面的例子为例,来解决一下异常
String[] array = {"我错了"}
try
{
//将可能异常的语句放入try中
String string = array[1];
System.out.println("我运行了吗1");
}catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("捕获到异常");
}
System.out.println("我运行了吗2");
输出的结果是
捕获到异常
我运行了吗2
根据输出结果,我们可以得出结论:当系统捕获到异常的时候,catch中的代码会运行,并且会继续向下执行,不会停止.
一般来说,异常捕获的流程大概可以分为这几步:1.发生异常 2,系统会自动生成一个异常对象并返回给调用者
3.调用者如果使用try … catch…去解决异常的话,如果返回的异常能被catch捕获的话,程序就会继续运行下去,如果没有捕获,程序就会把错误抛给上一级jvm,jvm就会输出异常并终止程序
其实在try… catch … 后面我们有时候还会看见finally{ },finally{ }中的方法无论什么情况下都会执行的,不会是否捕获到异常,也不论程序是否被终止.
例如:
String[] array = {"我错了"}
try
{
//将可能异常的语句放入try中
String string = array[0];
System.out.println(string);
return; //return终止了程序
}catch(ArrayIndexOutOfBoundsException e) //catch中并没有捕获到异常
{
System.out.println("捕获到异常");
}finally
{
System.out.println("我是finally中的方法");
}
运行后输出的结果是:
我错了
我是finally中的方法
通过运行结果我们可以看出,即使catch并没有捕获到异常,而且return已经在前面结束了程序,finally中的代码还是运行了,这就说明了,finally中的程序无论什么情况都会运行的.
异常总的来说可以分为两类:1.运行异常 2.非运行异常也可以说编译异常
运行异常一般来说都是代码的错误造成的.而编译异常则是系统对问题的提前预警,强制你去处理.
上面我们讲到的异常都是系统类的异常,下面我们根据系统处理异常的流程,可以构造一个自定义的异常
例:创建一个学生类,学生的变量是年龄,要求:学生的年龄是0~60,超出就会报错
public class Student {
private int age;
public Student() {
super();
}
public int getAge() {
return age;
}
public void setAge(int age) throws AgeOutOfBoundsException //标注一下,该方法可以抛出一个异常
{
if (age >0 && age<=60)
{
this.age = age;
}
else
{
AgeOutOfBoundsException ageOutOfBoundsException
= new AgeOutOfBoundsException("年龄异常");
throw ageOutOfBoundsException;//抛出异常,将异常跑给上一级(谁调用抛给谁)
}
}
}
class AgeOutOfBoundsException extends Exception //自定义一个异常,要继承于Exception
{
//重写父类的构造方法
public AgeOutOfBoundsException(String message)
{
super(message);
}
}
//然后在main方法中调用
public static void main(String[] args) throws AgeOutOfBoundsException//因为set方法会给异常抛给main方法,然后main方法会将异常抛给虚拟机,所以main方法也要标注一下,可以抛出一个异常
{
Student student = new Student();
student.setAge(-16);
}
这时运行,就会输出:
AgeOutOfBoundsException: 年龄异常
这里我们要注意一下throw和throws的区别:
throw是指将一个异常抛给上一级,而throws则是标注一个方法,表示该方法是运行抛出异常的
在我们学习Exception的时候,要注意区分一下Exception的几个方法的区别
Exception e = new Exception("我是一个异常类的对象");
//打印出来的是e的类名和e的异常信息
System.out.println(e);
//打印出来的是e的异常信息
System.out.println(e.getMessage());
//打印出来的是类名+异常信息+异常对象出现的位置,jvm默认打印出来的就是这个
e.printStackTrace();