一、Java程序中错误的分类
1、编译错误:
编译器能够检测到的错误,一般是语法错误。此时不能将源代码(.java)编译成可执行的字节码文件(.class)。
2、运行错误:
程序运行时产生的错误,例如被0除、数组下标越界等等。
3、逻辑错误:
这是机器本身无法检测的,需要程序员对运行结果及程序逻辑进行分析才能发现,逻辑错误可能会导致运行结果错误,有时也可能会导致运行错误。
二、Throwable类1、Error类(错误):
Error类则包括了一些较少发生的内部系统错误。这些错误都是严重的错误,用户程序无法进行处理,只能通知使用者关闭程序。例如内存不足、虚拟机内部错误等等。
2、Exception类(异常):
Exception类是所有异常类的父类,包括了一些由程序本身及环境所产生的错误。应用Java的异常处理机制,异常(Exception)可以被捕获并进行相应的处理。例如数组下标越界、被0除等等。
三、异常处理机制的概念 1、Java 对异常进行了分类,不同类型的异常分别用不同的 Java 类表示,所有异常的根类为 java.lang.Throwable
2、Throwable下面又派生了两个子类:Error和Exception,Error表示应用程序本身无法克服和恢复的一种严重问题。Exception 表示程序还能够克服和恢复的问题,其中又分为非检查(运行)异常和检查异常,非检查异常可以避免、不强制必须处理,在运行的时候才会出现异常,只有RuntimeException类或者其子类以及子类的子类是运行异常,其他异常类都是检查异常。非检查异常例如,数组下标越界(ArrayIndexOutOfBoundsException),空指针异常
(NullPointerException)、类转换异常(ClassCastException);检查异常是运行环境的变化或异常所导致的问题,
不可避免 在编译期必须进行异常处理,否则无法通过编译。
3、java中异常必须try…catch处理或用throws声明继续抛给上层调用方法处理。
1、检查异常:
(1)不可避免 在编译期必须进行异常处理,否则无法通过编译。
(2)常见检查异常:
名字 | 含义 |
---|---|
ClassNotFoundException | 无法找到指定的类时发生该异常。 |
FileNotFoundException | 访问一个不存在的文件时发生该异常。 |
IOException | 通常的I/O错误。 |
2、非检查(运行)异常:
(1)可以避免 不强制必须处理,在运行的时候才会出现异常,只有RuntimeException类或者其子类以及子类的子类是运行异常,其他异常类都是检查异常。
(2)常见非检查(运行)异常:
名字 | 含义 |
---|---|
ArithmeticException | 算术异常、如果除数为0,则发生该异常。例:int i = 12 / 0 |
ArrayIndexOutOfBoundsException | 数组下标越界异常、数组下标越界异常。例:int[] a = { 1 }; a[1] = 2; |
NullPointerException | 空指针异常 对象未实例化时访问该对象,即对象为空时,任然通过对象.方法调用。则发生该异常。例:int[] a = null; a.toString(); |
ClassCastException | 类型转换异常 |
Numberformatexception | 表示数字格式化异常 |
注意:一个方法一次只能出现一个异常。因为遇到一个异常后,程序就不会继续向下执行了。
五、异常的处理1、throw 关键字:
throw new ArithmeticException();手动抛出异常。
2、java异常的传递:
异常沿着方法的调用链反方向传递。
3、java异常的处理方式:
1、throws声明处理异常:
(1)需要一级一级的抛异常,只会显示出异常信息,不会对异常信息进行处理,异常后面的代码不会运行。
(2)可以一次申明多个异常,每个异常中间用,隔开即可。如下 :
public void test3()throws NullPointerException,ArithmeticException,
ArrayIndexOutOfBoundsException, ClassCastException , NumberFormat Exception {
System.out.println("----------test3 before----- ");
Scanner sc = new Scanner(System.in) ;
}
(3)如果多个异常有公共的父类,可以用父类异常进行替换,例如上面的可以替换成下面代码:
public void test3()throws Exception {
System.out.println("----------test3 before----- ");
Scanner sc = new Scanner(System.in) ;
}
(4)用switch循环声明多个异常的时候,必须把switch里面声明的异常全写上,或者用它们共同的父类替换:
public void test3()throws NullPointerException , Arithmeti cException,
ArrayIndexOutOfBoundsException, ClassCastException, NumberFormatException {
System. out. println("----------test3 before----- ") ;
Scanner sC = new Scanner(System.in) ;
inti=sc.nextInt();
switch (i) {
case 0 :
throw new ArithmeticException( );
case 1 :
throw new NullPointerException();
case 2 :
throw new Array IndexOutOfBoundsException( );
case 3:
throw new ClassCastException( );
case 4:
throw new NumberFormatException();
}
System. out. println("----------test3 end----- " ) ;
}
2、try…catch捕获式处理异常:
(1)会显示出异常信息,同时对异常信息进行处理,异常后面的代码会继续运行。
(2)try…catch可以处理多个异常,一个try{}可以对应多个catch(),也可以在一个catch()里面写多个异常,用或:|隔开,这种方式称为muti-catch;如果出现多个异常,可以将ctrch后面的类换成这些类的父类。如下 :
try{
//########################
} catch (ArithmeticException e1) {
e1. printStackTrace( );
}catch ( NullPointerException e2) {
e2. printStackTrace( );
}catch (Array IndexOutOfBoundsException e3) {
e3. pr intStackTrace();
}catch (ClassCastException e4) {
e4. printStackTrace( ) ;
}catch (NumberF ormatException e) {
e. printStackTrace( ) ;
System. out . println("----------test3 end----- ");
try{
//#################
} catch (ArithmeticException | NullPointerException | Array IndexOutOfBoundsException
e1. printStackTrace( ) ;
}
System. out . println("-----test3end-- ");
(3)catch的执行前提:catch()块里面的异常只有在和try语句里面捕获到异常相匹配的时候才会执行,如果try语句块中没有匹配到对应的异常,则catch块里面的语句不会执行。
3、try…catch…finally:
(1)finally没有执行的两种情况:
① 在执行try之前已经return
② 在try语句块中执行System.exit(0);方法
(2)fially的执行时机:如果try里面有返回值,则finally语句是在try的return语句执行之后,finally语句块外边最终的return结果返回到调用此方法之前执行。
4、Final,finally, finalize三者的区别:
(1)final:用于声明属性,方法和类,分别表示属性不可变,方法不可重写(覆盖),被其修饰的类不可继承。
(2)finally:异常处理语句结构的一部分,表示总是执行。
(3)finalize:Object类的一个方法,在垃圾回收器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。该方法更像是一个对象生命周期的临终方法,当该方法被系统调用则代表该对象即将“死亡”,但是需要注意的是,我们主动行为上去调用该方法并不会导致该对
象“死亡”,这是一个被动的方法(其实就是回调方法),不需要我们调用。
1、子类重写父类方法时,重写的方法不能比被重写方法抛出更多更大的异常.
2、重写的方法抛出的异常只能是被重写方法抛出异常的子类(可以同时写多个异常子类)或相同。
try {
throw new NullPointerException("这是空指针异常");
} catch (Exception e) {
e.printStackTrace();
}
******************************************
java.lang.NullPointerException: 这是空指针异常
at test2.Sample.main(Sample.java:27)
catch(NullPointerException e) {
x=20;
System. out. println("catch. .."+x);
e.printStackTrace();
System.err.println(e. getMessage());
}finally {
}
运行后输出:test方法中出现空指针异常
八、自定义异常
1、场景:比如说输入密码,三次不正确的时候,抛出错误给予提示。
2、创建检查异常:
(1)继承Exception或除RuntimeException的其他子类。
(2)编写构造方法,无参和有参,通过super()将异常信息传递给父类。
3、创建运行(非检查)异常:
(1)创建运行异常需要继承runtimeException类。
(2)编写构造方法,通过super()将异常信息传递给父类。
public class MyCheckException extends Exception {
public MyCheckException() {
}
public MyCheckException(String msg) {
super(msg);
}
}
public static void test() throws MyCheckException {
throw new MyCheckException("这是自定义的检查异常");
}
class Test {
public static void main(String[] args) throws MyCheckException {
test();
}
}
九、思维导图