在使用计算机语言开发时,尽管代码没有问题,但在系统的运行过程中仍会遇到问题。简单来说就是代码运行时,由于各种原因导致程序不能正常的执行。
定义:Java语言中,将程序执行中发生的不正常的情况称为“异常”(这里我们认为开发过程中的语法错误和逻辑错误不是异常)。
分类:Java程序在执行过程中所发生的异常(广义上的一切不正常)事件可分为两类—Error和Exception
Error:Java虚拟机无法解决的严重问题,一般不编写针对性代码进行处理。会出现Error的情况一般是内存空间不够,JVM系统内部错误,资源耗尽等等严重问题。(本文我们不讨论Error的问题)
Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性代码进行处理,即使用java的异常处理机制,控制后面的代码继续执行。(本文我们只讨论在编译程序时出现最多的Exception问题)
1.遇到异常就终止程序的运行。
2.编写程序时,就要考虑到异常的检测、异常消息的提示、以及异常的处理。
如何捕获异常?答:捕获异常最理想的阶段就是在编译期间,但是仍有部分异常是出现在运行期间的。这样就会使异常出现两种不同的情况,编译时异常和运行时异常。
Throwable类:这是Java语言中所有错误和异常的顶级(超)类,它就是一个祖宗级别的大佬类。错误就是Error,可能会是系统错误,程序往往是不处理的。异常就是Exception,这是所有异常类的父类,也是编程人员最最关心的。
Exception类:就是异常,上面我们也说到了Exception类有两种:一种是运行期异常另一种就是编译期异常。
运行期异常:程序运行时抛出的异常,所有RuntimeExcepetion的子类都是运行期异常。如:
ArithmeticException 数学算数异常
NullPointerException 空指针异常
ArrayIndexOutOfBoundsException 数组索引越界异常
......
编译期异常:除去运行期的异常都是编译期异常,一般也称检测异常,会在编译的时候就提示有误,需要你在代码编译期间对其作出修改。
IQException
SQLException
ParseException
......
代码示例
//示例1
//ArrayIndexOutOfBoundsException 抛出以表示使用非法索引访问数组。 索引为负数或大于或等于数组的大小。
int [] a = new int[5];
a[5] = 10;
System.out.println(a[5]);
//上面的代码运行后出现如下异常
/*
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 (5表示非法索引值)
at yichang.ExceptionDemo1.main(ExceptionDemo1.java:7)(//7表示在第七行出现错误)
*/
//示例2
//NullPointerException 空指针异常 用程序尝试在需要对象的情况下使用null时抛出
String a = null;
a.length();//实质是null.length*/
JVM默认的异常处理方式是当控制台抛出对应类型的异常对象(异常信息)时终止程序,而Java编程语言使用异常处理机制为程序提供错误处理的能力。
1.程序中预先设置好对付异常的处理办法
2.程序开始运行
3.出现异常
4.对异常进行处理
5.处理完毕,继续执行下面的代码
Java中的异常处理都是通过五个关键字来实现的:try、catch、finally、throw、throws。
关键字 | 作用 |
---|---|
try | 捕获异常,执行可能产生的异常代码。 |
catch | 捕获异常。 |
finally | 无论是否发生异常,finally内的代码都会执行。 |
throw | 声明异常,声明方法中可能抛出的各种异常。 |
thros | 手动抛出异常。 |
try、catch、finally一般是互相配合使用,他们的基本语法是:
try{
//可能出现异常的代码,代码量尽量缩小
}catch(上面异常代码的异常类型){//当try出现异常时,执行catch
//处理异常的方式
}finally{
//必须执行的代码
}
代码示例
public class ExceptionDemo5 {
//try{}catch(){}finally
public static void main(String[] args) {
//语法格式
/*
* try{
* //可能出现的异常代码,代码量范围尽量缩小
* }catch(异常类型){
* //出现异常时的处理方式
* }finally{
* //必须执行的代码
* }
*/
int a = 10;
int b = 2;
try{
System.out.println(a/b);
}catch(Exception e){
System.out.println("错误");
}finally{
System.out.println("必须执行");//输出
}
int c = 0;
try{
System.out.println(a/c);
}catch(Exception e){
System.out.println("错误");
}finally{
System.out.println("必须执行");//输出
}
}
}
检测可能会发现异常的代码块,try块中任何一条语句发生异常,下面的代码将不会被执行,程序将跳转到异常处理代码块中,即catch块。因此,不要随意将不相关的代码放入到try块中,因为随时可能会中断执行。
把抓到的类型匹配的异常捕获,保证程序能够继续运行下去,catch语句必须紧跟着try语句之后,称为捕获异常,也就是异常处理函数,一个try后面可以写多个catch,分别捕获不同类型的异常,要从子类往父类的顺序写,否则有编译错误。
finally里面的语句块总会执行,一段代码只能有一个finally语句。
与其它对象一样,都可以访问一个异常对象的成员变量或调用它的方法。
获取异常信息,返回一个字符串。就像下面这个示例中的Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 5 这里的5就是getMessage()可以得到的字符串.
//示例1
//ArrayIndexOutOfBoundsException 抛出以表示使用非法索引访问数组。 索引为负数或大于或等于数组的大小。
int [] a = new int[5];
a[5] = 10;
System.out.println(a[5]);
//上面的代码运行后出现如下异常
/*
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 (5表示非法索引值)
at yichang.ExceptionDemo1.main(ExceptionDemo1.java:7)(//7表示在第七行出现错误)
*/
获取异常类名和异常信息, 以及异常出现出现在程序中的位置, 无返回值。如上面示例中的:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at yichang.ExceptionDemo1.main(ExceptionDemo1.java:7)
代码示例
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class GetExceptionDataDemo {
public static void main(String[] args) {
String str = "2020-11-10";
SimpleDateFormat stf = new SimpleDateFormat("yyyy.MM-dd");
try {
Date date = stf.parse(str);
} catch (ParseException e) {
System.out.println(e.getMessage());//Unparseable date: "2020-11-10"
e.printStackTrace();
/*
* java.text.ParseException: Unparseable date: "2020-11-10"
at java.text.DateFormat.parse(DateFormat.java:366)
at yichang.GetExceptionDataDemo.main(GetExceptionDataDemo.java:12)
*/
}
}
}
1. throws,定义一个方法的时候可以使用throws关键字声明,表示此方法不处理异常,而交给方法调用处进行处理。
语法格式:
public void test throws 异常1,异常2,异常3....{
}
2.任何方法都可以使用throws关键字声明异常类型,包括抽象方法。
3.子类重写父类中的方法,子类方法不能声明抛出比父类类型更大的异常。
4.使用了throws的方法,主要指编译期异常,调用时必须处理声明的异常,要么使用try-catch,要不继续使用throws声明。
代码示例—父
public abstract class ThrowsDemo {
public abstract void chufa(int a, int b) throws Exception;
}
代码示例–子
import java.text.ParseException;
public class ThrowstestDemo extends ThrowsDemo{
@Override
public void chufa(int a, int b) throws ParseException {
System.out.println(a/b);
}
public static void main(String[] args) throws ParseException {
new ThrowstestDemo().chufa(2,2);//调用方法时必须要对异常方法进行处理 继续throws or try-catch
}
}
1.throw关键字用于显式的抛出异常,抛出的是一个异常类的实例化对象。
2.在异常处理中,try语句要捕获的是一个异常对象,那么此对象也可以自己抛出。
3.在程序中主动抛出异常对象,在构造方法中可以填入错误信息。
代码示例
public class ThrowDemo {
public static void main(String[] args) {
int a =10;
int b =0;
try{
System.out.println(a/b);
}catch (ArithmeticException n){
throw new ArithmeticException("分子不能为0");//在程序中主动抛出异常对象,在构造方法填入错误信息。
}
}
}
1.throw用于方法体中, 用来抛出一个实际的对象, 使用throw后, 要么使用try-catch捕获异常,要么使用throws声明异常
2.throws用于方法声明处, 用来声明该方法可能发生的异常类型, 可以是多个异常类型, 用来强制调用该方法时处理这些异常.
3.抽象方法也可以使用throws.
1.自己定义的异常类, 也就是API中标准异常类的直接或间接子类
2.作用: 用自定义异常标记业务逻辑的异常,避免与标准异常类混淆
3.自定义异常类的语法:
public class 异常类名 extends Exception/RuntimeException{
public 异常类名(String msg){
super(msg);
}
}
4.自定义异常类通常不写其他方法,只重载需要使用的构造方法
5.继承Exception, 在方法中使用throw抛出后, 必须在方法中try-catch或者throws抛出
代码示例
//自定义异常
//继承了一个Exception,使得自定义的类成为了一个异常类
public class fenshuExceptionDemo9 extends Exception{
// 定义了自身异常类的一个构造方法
public fenshuExceptionDemo9(){
// super() 调用了继承的Exception的一个传参的构造方法
super("分数不合法");
}
public fenshuExceptionDemo9(int a){
super("分数不合法");
}
}