Java中的异常
在程序运行时发生了不正常的情况,此时由系统中断程序的运行,包含异常信息、异常类名、异常的位置。
异常分类
- Error 错误
由系统原因造成的,一般是系统资源分配冲突时或系统崩溃等原因,这一类Error错误,对于程序员来说是无法处理的 - Exception
由于程序原因造成的,一般是运算、I/O读取等原因,这一类Exception异常,可以进行处理
Java中异常类的体系
Throwable、Error、Exception
在Java中如何处理异常?
1、捕获异常处理
try{
可能出现异常的语句;
}catch(异常类型 对象名){
处理异常语句;
}
2、抛出异常
-
声明方法时抛出异常
方法名() throws 异常类名[,异常类名,异常类名] {}
-
在方法中抛出异常
RuntimeException :非受控异常(运行时异常)
案例
public class Demo {
static int divide(int a, int b) throws ArithmeticException {
int result = 0;
result = a / b; //当发生异常时,向调用者抛出异常
//当异常从某一位置抛出后,其下的语句不会被执行
System.out.println("计算结果完成....");
return result;
}
public static void main(String[] args) {
//输入两个数
Scanner scanner = new Scanner(System.in);
//将数字字符串转成数值类型
int a = scanner.nextInt();
int b = scanner.nextInt();
scanner.close();
try {
int r = divide(a, b);
System.out.println(r);
} catch (Exception e) { //可以处理所有异常,即Exception类是所有异常的父类
e.printStackTrace();
}
}
}
运行结果
多个异常处理方式
try{
}catch(异常类名 对象名){
}catch(...){
}catch(...){
}
注意:处理多个异常类时,异常的子类所在的catch语句要放在最上面。
案例
public class Demo {
static class Person {
String name;
public Person(String name) {
this.name = name;
}
public String toString() {
return "[name=" + name + "]";
}
}
static void sub(int a, int b, int[] nums, Person p) {
try {
int r = a / b;//此行如果出现了异常,则下行代码不会执行
r = nums[5] / 9;
System.out.println(p);
} catch (ArithmeticException e) {
System.out.println("除数为0了...");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组的索引值越界了,数组的长度小于6...");
} catch (NullPointerException e) {
System.out.println("访问的对象是null");
} catch (Exception e) { //异常类的父类所处于的catch语句要放在最后
e.printStackTrace();
}
}
public static void main(String[] args) {
int[] nums = {9, 10, 8, 66, 22, 109};
sub(10, 2, nums, new Person("张三"));
sub(10, 0, new int[3], null);
}
}
抛出异常
-
抛出多个异常
在方法声明的后边,使用 throws 异常类型列表 语句。
抛出一个异常
throw new RuntimeException("异常信息")
案例
public class Demo {
static class Person {
String name;
public Person(String name) {
this.name = name;
}
public String toString() {
return "[name=" + name + "]";
}
}
//抛出多个异常,抛给调用者处理
static void sub(int a, int b, int[] nums, Person p)
throws ArithmeticException, IndexOutOfBoundsException, NullPointerException {
int r = a / b;//此行如果出现了异常,则下行代码不会执行
r = nums[5] / 9;
//System.out.println(p.toString());
}
static void div(int a, int b) {
if (b == 0) {
//抛出异常
throw new RuntimeException("除数为0");
}
}
public static void main(String[] args) {
int[] nums = {9, 10, 8, 66, 22, 109};
//sub(10,2,nums,new Person("张三"));
try {
sub(10, 4, new int[7], null);
div(9, 0);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组长度小于6");
} catch (IndexOutOfBoundsException e) { //父类的异常处理放在子类异常处理的下方
System.out.println("索引越界。。。");
} catch (Exception e) {
e.printStackTrace();
}
}
}
处理异常的格式(正规的)
try{
//资源分配的语句
}catch(...){
}finally{
//肯定执行的语句,一般是释放资源的语句,
//注: 如果try语句中包含return 语句,finally语句在return之前执行
}
案例
public class Demo {
static class Student{
private String name;
public Student(String name){
this.name=name;
}
public int div(int a,int b){
return a/b;
}
public String toString(){
return name;
}
}
public static void main(String[] args){
Student s=new Student("张三");
try{
s.div(10,0);
return ;
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println(s.toString());
s=null;//s所指向的堆内存变是垃圾了,可以被gc回收
System.out.println("回收资源...");
}
}
}
自定义异常
自定义异常类步骤
1、创建类,并继承Exception
2、提供构造方法,可以调用父类的构造方法
3、使用自定义的类时在方法中,根据条件判断的结果,再通过throw关键向方法的调用者抛出异常
如:
void method(int a){
if(a<0){
throw new 自定义异常类型("异常信息");
}
注意:对于抛出的自定义的Exception异常,必须要处理
案例
public class Demo {
static class MyException extends Exception {
public MyException() {
super("自定义异常");
}
public MyException(String msg) {
super(msg);
}
}
static void isZero(int n) throws MyException {
if (n < 0) {
//抛出数值不能小于0的异常
throw new MyException("数值不能小于0!!"); //抛出的一般性异常必须要处理:捕获或抛出
}
System.out.println("大于0的值--》" + n);
}
public static void main(String[] args) {
try {
isZero(-1);
} catch (MyException e) {
e.printStackTrace();
}
}
}
补充
Error和Exception有什么区别?
Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;Exception表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。
try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,什么时候被执行,在return前还是后?
会执行,在方法返回调用者前执行。
阐述final、finally、finalize的区别
- final:修饰符(关键字)有三种用法:如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。将变量声明为final,可以保证它们在使用中不被改变,被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。被声明为final的方法也同样只能使用,不能在子类中被重写。
- finally:通常放在try…catch…的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。
- finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。
说出下面运行结果:类ExampleA继承Exception,类ExampleB继承ExampleA。
try {
throw new ExampleB("b")
} catch(ExampleA e){
System.out.println("ExampleA");
} catch(Exception e){
System.out.println("Exception");
}
输出:ExampleA。
常见的运行时异常?
- NullPointerException (空指针异常)
- IndexOutOfBoundsException (下标越界异常)
- ClassCastException (类转换异常)
- IllegalArgumentException (非法参数异常)
- ArithmeticException(算术异常)