面向对象基础篇 – 程序异常

面向对象基础篇 – 程序异常

在计算机程序运行的过程中,总是会出现各种各样的异常,如何处理这些异常

常见的一些错误

空指针异常 NullPointerException
public class Demo {
    public static void main(String[] args) {
        int[] arr = null ;
        System.out.println(arr[0]);
    }
}
/*
Exception in thread "main" java.lang.NullPointerException
	at Demo.main(Demo.java:4)
	*/
角标越界异常 IndexOutOfBoundsException
public class Demo {
    public static void main(String[] args) {
        int[] arr ={1,2,3} ;
        System.out.println(arr[3]);//ArrayIndexOutOfBoundsException
        String str = "Hello";
        System.out.println(str.charAt(10);//StringIndexOutOfBoundsException
    }
}

算数异常 ArithmeticException
public class Demo {
    public static void main(String[] args) {
        System.out.println(10/0);//ArithmeticException
    }
}

数字格式化异常 NumberFormatException
public class Demo {
    public static void main(String[] args) {
        String str = "dss";
        System.out.println(Integer.parseInt(str));//NumberFormatException
    }
}
栈溢出 StackOverflowError
public class Demo {
    public static void main(String[] args) {
        show();
    }
    private static void show() {
        show(); //StackOverflowError
    }
}
堆内存溢出 OutOfMemoryError
public class Demo {
    public static void main(String[] args) {
        show();
    }
    private static void show() {
        int[] arr = new int[100000000];//OutOfMemoryError
        show();
    }
}

对于一个递归函数来说,即使函数递归次数有限,但也有可能出现栈内存溢出,或者堆内存溢出的情况,对于这种随机出现的错误,是不可避免的。

对于一个健壮的程序,他应该是能够提前预知并处理一些问题的,而不是在遇到错误的时候直接终止

错误预处理的方法

使用错误代码标记
public class Demo {
    public static void main(String[] args) {
        int[]  arr = {1,2,3,4,5,6};
        int index = 10;
        int num = getNum(arr ,index);
        if (num == -1) {
            System.out.println("数组为空");
        }else if (num == -2) {
            System.out.println("角标越界");
        }else {
            System.out.println(num);
        }
        System.out.println("main end ...");
    }

    private static int getNum(int[] arr, int index) {
        if(arr == null) return -1 ; //数组为空
        else if(arr.length<=index) return -2 ; //角标越界
        return arr[index];//返回对应值
    }
}

如上,通过错误代码标记,我们对错误进行处理,且不停止程序

但是,这种方法往往存在很大的弊端:

假如,错误代码与数组存储值相同时,则会产生冲突

异常对象

java是一门面向对象的编程语言,因此,异常其实在java种也可以看作是一个对象

通过throw来抛出异常对象

语法: throw +异常对象

public class Demo {
    public static void main(String[] args) {
        int[]  arr = {1,2,3,4,5,6};
        int index = 10;
        int num = getNum(arr ,index);
        System.out.println(num);
        System.out.println("main end ...");
    }

    private static int getNum(int[] arr, int index) {
        if(arr == null) {
            //如果内部无法解决问题,则抛出错误异常交给调用者处理
            throw new NullPointerException("数组为空");//数组为空
        }
        else if(arr.length<=index) {
            ArrayIndexOutOfBoundsException e = new ArrayIndexOutOfBoundsException("角标越界");
            throw e ;
        }; //角标越界
        return arr[index];//返回对应值
    }
}
通过throws声明异常

某一个函数内部产生编译时异常对象,但是该函数内部并不会处理该问题,则交由调用者处理
声明 就是告诉调用者 我函数内部可能会出现问题 但是内部不会解决 交由调用者来解决
如果没有任何人来具体处理的话,可能会导致程序中断
throws + 异常类 在函数声明之后

public class Demo {
    public static void main(String[] args) {
        int[]  arr = {1,2,3,4,5,6};
        int index = 10;
        int num = getNum(arr ,index);
        System.out.println(num);
        System.out.println("main end ...");
    }

   private static int getNum(int[] arr, int index) throws NullPointerException ,ArrayIndexOutOfBoundsException {
        return arr[index];//返回对应值
    }
}
throw 和 throws 的异同
  • 相同点
    • 两者在抛出异常时,抛出异常的方法并不负责处理,顾名思义,只管抛出,由调用者负责处理。
  • 不同点
    • throws用于方法头,表示的只是异常的申明,而throw用于方法内部,抛出的是异常对象
    • throws可以一次性抛出多个异常,而tthrow只能一个
    • throws抛出异常时,它的上级(调用者)也要申明抛出异常或者捕获,不然编译报错。而throw的话,可以不申明或不捕获(这是非常不负责任的方式)但编译器不会报错。

即使我们不对异常进行声明或者抛出,JVM也会自动生成异常对象

Throwable类

错误的问题多了,那么就可以将共性进行抽取,抽取出来的结果 异常体系

Throwable 类是 Java 语言中所有错误或异常的超类

只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出

类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。

实现子类
  • Error

程序中出现的一些重大错误,这些错误直接和JVM、内存、硬件有关,

不需要预判如果一旦出现该错误,则不会有挽回的情况,除非重新更改代码

例如:

IOError 输入输出错误
VirtualMachineError 虚拟机错误

StackOverflowError
OutOfMemoryError

  • Exception

程序中出现的一些普通错误,这些错误可以在编码的时候预先进行预判和处理有挽回的机会

例如:

编译时异常:Exception的其他子类
对于编译时异常而言,在程序编译期间,未运行之前,能够预判到的一些错误
需要预先的处理(声明、捕获)
FileNotFoundException 文件未找到异常
File file = new File(“C:\abc.txt”);
ParseException 解析异常
Date date = dateFormat.parse(“2015-08-08 15:30:31”);

运行时异常:Exception中RuntimeException类及其子类 对于运行时异常而言,只有程序在运行的时候才能判断代码是否出错 一旦程序运行了并且出错,这种错误一般不会进行额外的处理(声明、捕获) 这些异常 也一般都是有JVM来进行判断和抛出的 ArithmeticException ClassCastException IndexOutOfBoundsException ArrayIndexOutOfBoundsException, StringIndexOutOfBoundsException NullPointerException

注意

RuntimeException与Error都是没必要进行处理的错误,一旦出错只能认栽

Exception的其他子类 都是需要进行处理的(声明,捕获)

异常捕获

某一个函数内部产生编译时异常对象,但是该函数内部会自己解决,不再交由调用者处理
捕获 就是函数内部来解决出现的问题,不让该问题继续向上层抛出/传递
有人处理了,不会导致程序中断
try{} 尝试执行某一段代码
catch(){} 如果try中的代码出现问题,则有catch中的语句来处理该问题

public class Demo {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        int index = 10;
        int num = getNum(arr , index);
    }

    private static int getNum(int[] arr, int index)  {
       try{
           return arr[index];
       }catch (ArrayIndexOutOfBoundsException | NullPointerException e) {
           System.out.println("出现错误");
           return -1 ;
       }
    }
}
/*
输出:
出现错误
*/

if try中出现异常
走catch代码
else
接着往后直行
try语句在尝试执行时,尽量把范围缩小,不要全部代码都放到try语句中
因为try代码中,某一行一旦发生异常,则try中后续的代码不会执行!!!
一般把和异常无关的内容尽量放到try外面

catch可以一次性捕捉多个异常问题 可以使用多个catch语句块,来对不同的异常进行分别的处理
也可以一次全部捕捉
也可以直接捕获Exception

 /*catch (Exception e) {

                }*/
finally代码块

无论是否出现异常都会执行的代码片段

一般用于释放资源,关闭资源

public class ExceptionDemo09 {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        int index = 0;
        int result = show(arr, index);
        System.out.println(result);
    }

    private static int show(int[] arr, int index) {
        try {
            System.out.println("try code...");
            int num = arr[index];
            System.out.println(num);
            //finally代码执行....
            return 0;   //没有异常 先finally 后return 0;
        } catch (Exception e) {
            System.out.println("catch code...");
            //finally代码执行....
            return 2;   //有异常时 先finally 后return 2;
        } finally {
            System.out.println("finally code...");
            return 3;
        }
//        return 1; //如果catch中 和 finally中 有return 此处被屏蔽不可达代码
    }
}

/*
try有return 0 catch没有 finally没有 函数末尾有return 1
没有异常 try->finally->return 0
产生异常 try->catch->finally->return 1
try有return 0 catch有return 2 finally没有 函数末尾return 1被屏蔽
没有异常 try->finally->return 0
产生异常 try->catch->finally->return 2
所以会发现 无论是否有异常 要么return 0 要么return 2 所以return 1被屏蔽了
try有return 0 catch有return 2 finally有return 3 函数末尾return 1被屏蔽
无论是否异常 都return 3
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值