程序错误分为三种:1.编译错误;2.运行时错误;3.逻辑错误。
(1)编译错误是因为程序没有遵循语法规则,编译程序能够自己发现并且提示我们错误的原因和位置,这个也是大家在刚接触编程语言最常遇到的问题。
(2)运行时错误是因为程序在执行时,运行环境发现了不能执行的操作。
(3)逻辑错误是因为程序没有按照预期的逻辑顺序执行。异常也就是指程序运行时发生错误,而异常处理就是对这些错误进行处理和控制。
异常的定义:在程序中,错误可能产生于程序员没有预料到的各种情况,或者超出程序员可控范围的环境,例如用户的坏数据、试图打开一个不存在的文件等。为了能够及时有效地处理程序中的运行错误,Java 专门引入了异常类。
Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。异常和错误的区别是:异常能被程序本身可以处理,错误是无法处理。
由于在程序出现意外情况时,往往有严重的情况和不严重的情况,也会是可以解决的情况。所以将异常分为Error(不可纠正的错误)和Exception(可以解决的错误)。
常见的异常有:
- NullPointerException - 空指针引用异常
- ClassCastException - 类型强制转换异常。
- IllegalArgumentException - 传递非法参数异常。
- ArithmeticException - 算术运算异常
- ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
- IndexOutOfBoundsException - 下标越界异常
- NegativeArraySizeException - 创建一个大小为负数的数组错误异常
- NumberFormatException - 数字格式异常
- SecurityException - 安全异常
- UnsupportedOperationException - 不支持的操作异常
这些异常都是运行时的异常,属于RuntimeException
异常的处理办法:1、所有的异常,都是Throwable的子类,都是可抛出的
2、捕获异常
抛出异常:抛异常的方法有两个 Throw和Throws
Throws:抛出异常的类型,自己不做处理。谁调用,谁接异常,在做相应的处理。
Throw:直接将异常的对象抛出,抛给JVM
Throws将异常抛给调用着,本质上是没有处理异常的,如果一层一层的抛给调用者,最终回由JVM接手异常,JVM处理时会将程序截至运行。
Throws和Throw的区别:
1、书写格式上
Throws在方法名后加上Throws【异常可能的类型】,【】中可以包含多种异常类型,中间用,隔开
Throw在方法体中,出现异常的位置,直接将异常抛出
public class Demo02 {
public static void main(String ars[]) throws Exception {
L2 l=new L2();
l.throwTest1();//jvm会终止程序
try{
l.throwsTest();//L2类向上抛 由主函数解决
} catch (Exception e){
System.out.println("try_cath自定义解决");
}
l.throwTest();
}
}
class L2{
public void throwsTest() throws Exception{//Exception
int a = 10;
int b = 0;
int r = a / b;
System.out.println(r);
}
public void throwTest() {
int arr[] = new int[2];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
int index=5;
if(index<0||index>=arr.length)
{
throw new ArrayIndexOutOfBoundsException();//throw跟异常的解决方法
//直接在该函数解决一场
}
System.out.println(arr[5]);
}
2、在抛的对象上
throw是语句抛出一个异常。
throws是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常)
- Throws出现在方法函数头;而Throw出现在函数体。
- Throws表示出现异常的一种可能性,并不一定会发生这些异常;Throw则是抛出了异常,执行Throw则一定抛出了某种异常。
- 两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
捕获异常:try-catch-finally
try{
//监控区
}
catch(异常的对象){
//处理
}
try后的一对大括号将一块可能发生异常的代码包起来,称为监控区域。
Java方法在运行过程中出现异常,则创建异常对象。将异常抛出监控区域之外,由Java运行时系统试图寻找匹配的catch子句以捕获异常。若有匹配的catch子句,则运行其异常处理代码,try-catch语句结束。
匹配的原则是:如果抛出的异常对象属于catch子句的异常类,或者属于该异常类的子类,则认为生成的异常对象与catch块捕获的异常类型相匹配。
注意:一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,就意味着整个try-catch语句结束。其他的catch子句不再有匹配和捕获异常类型的机会。
class Demo01 {
public static void main(String[] args)
{
L1 l=new L1();
l.caseTest1();//结果为:分母为零
l.caseTest2();//结果为:下标越界
//异常的抛出与执行顺序有关
//case截获异常时,越往下,截获异常的等级行该越小
l.caseTest3();//系统抛出异常
//原因此处无对应的异常得解决办法
}
}
class L1{
public void caseTest1(){
int a=0;
try {
int b=3/a;
int arr[]=new int[2];
System.out.println("访问arr[2]:"+arr[2]);
} catch (ArithmeticException e)
{
System.out.println("分母为零");
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("下标越界");
}
}
public void caseTest2(){
int a=0;
try {
int arr[]=new int[2];
System.out.println("访问arr[2]:"+arr[2]);
int b=3/a;
} catch (ArithmeticException e)
{
System.out.println("分母为零");
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("下标越界");
}
}
public void caseTest3(){
int a=0;
try {
int arr[]=new int[2];
System.out.println("访问arr[2]:"+arr[2]);
int b=3/a;
} catch (ArithmeticException e)
{
System.out.println("分母为零");
}
// catch (ArrayIndexOutOfBoundsException e)
// {
// System.out.println("下标越界");
// }
}
}