异常
什么是异常:
程序在运行的时候,出现了不正常的情况
为什么需要异常处理:
在没有异常处理之前,正常的流程代码 和 异常处理的代码,相结合,可读性差。
简单的示例如下:
//写一个函数,根据下标获取对应字符串数组的值
public static String getValueByIndex(String[] strings,Integer index){
if(strings == null){
//如何处理异常
}
if(index < 0){
//如何处理异常
}
if(index >= strings.length ){
//如何处理异常
}
return strings[index];
}
异常处理:
在有异常的地方,直接new一个对象,然后抛出。。。。
利用类的的形式,将不正常的情况进行了描述与封装成了对象
异常的信息包含:错误的信息,错误的名称,错误的位置
异常类:
用来描述不正常情况的类,我们称为异常类,不同的类型的异常使用不同的异常类来描述
就是一种异常,对应一个异常类。
异常的体系
不正常的问题多了,也就是意味着异常类也也多了,我们将这些类的共性进行向上抽象,就形成了异常体系。异常类分成2个类别,Error,Exception
Throwable是所有异常的祖宗,所有可以被抛出的异常对象,必须具有可抛性,必须是Throwable的子类。只有作为此类(或其一个子类)的实例的对象由Java虚拟机抛出,或者可以由Java throw
语句抛出
Throwable所有子类的类名:它后缀能看出该类的含义,子类包含父类的名称,可读性强。
类别一:error
错误:不可处理的错误
特点:一般是JVM抛出的错误,这种问题一般不处理,直接修改代码
案例如下:
public class Demo {
public static void main(String[] args) {
String[] strings = new String[1024*1024*1024];
}
}
运行以上代码,会出现如下错误:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at day8.Demo.main(Demo.java:20)
因为JVM中一个进程默认为128M的空间,此时我的字符串数组strings容量已经远远超出了128M,所以就会出现下面的错误
类别二:Exception
对于异常,我们可以去捕获,并处理。
Exception的分类:
编译时检查:
(1)这类型的一次,在程序编译的时候,会被发现。
(2)除了RuntimeException(子类)以外,其他都是编译时检查
(3)往往编译时检查的Exception,如果不处理,开发工具直接报错。
运行时检查
(1)RuntimeException及其子类,这类型的错误一旦发生,程序基本就挂掉了,除非进行异常捕获。
(2)如果我们自定义的异常类,基本要么继承与Exception,要么继承RuntimeException
自定义异常
/**
* 必须继承Throwable或者其子类的类,在建立对象时
* 才具有可抛性
* 能throw
*/
/**
* 自定义一个标为负数时抛出的异常类
*/
class NegativeDemoException extends Exception{
public NegativeDemoException() {
super();
}
public NegativeDemoException(String msg) {
super(msg);
}
}
Throw与Throws的区别
都是抛,意义是一样的,只是使用位置不一样
Throw:
使用在函数内部
抛出的是异常对象
Throws:
使用在函数上
抛出的是异常类,可以抛出多个,中间用英文逗号隔开。
异常的处理
就是发现了异常,怎么办?
(1)声明方式,往调用者身上抛
(2)捕获异常,try catch
调用的函数,有几种异常,你就需要捕获几种异常。
注意:
(1)如果一个方法包含几个异常,那么调用者就需要catch几个,解决几个。
注意异常catch处理的顺序。
(2)finally这里面的代码,无论异常是否发生,都会执行。
(3)Exception常用方法
e. printStackTrace():打印异常的堆栈信息
e.getMessage():拿到异常信息
处理异常原则
如果你可以解决的异常,直接try,如果你不能解决,就把问题往上抛,让调用者解决。
Try里头的代码,不要太多。
以下是一个较为完整的自定义异常与处理异常的案例
/**
* 必须继承Throwable或者其子类的类,在建立对象时
* 才具有可抛性
* 能throw
*/
import javax.xml.soap.Text;
/**
* 自定义一个标为负数时抛出的异常类
*/
class NegativeDemoException extends Exception{
public NegativeDemoException() {
super();
}
public NegativeDemoException(String msg) {
super(msg);
}
}
/**
* 自定义一个数组为空时抛出的异常
*/
class NullPointDemoException extends Exception{
public NullPointDemoException() {
super();
}
public NullPointDemoException(String msg) {
super(msg);
}
}
class Test{
public static String getValueByIndex(String[] strings,Integer index) throws NullPointDemoException, NegativeDemoException {
if(strings == null){
//如何处理异常
throw new NullPointDemoException("该数组为空!");
}
if(index < 0){
//如何处理异常
throw new NegativeDemoException("该下标为负数!");
}
if(index >= strings.length ){
//如何处理异常
}
return strings[index];
}
}
public class Demo {
public static void main(String[] args) {
String []test = {"a","b","c","d"};
//String[] strings = new String[1024*1024*1024]; //抛出Error异常
try {
//此时抛出的是数组为空的异常
//String value = Test.getValueByIndex(null,3);
//此时抛出的时下标为负数的异常
String value = Test.getValueByIndex(test,-1);
} catch (NegativeDemoException e) {
e.printStackTrace();
e.getMessage();
} catch (NullPointDemoException e) {
e.printStackTrace();
e.getMessage();
}finally {
System.out.println("这里的代码无论如何都会执行");
}
}