异常(1)--初识异常

程序运行时发生的不被期望的事件,他阻止了程序按照程序员预期正常执行,这就是异常

java异常的分类和类结构图:

Throwable为异常的顶级父类

                           Error和Exception为Throwable的子类:

    异常(1)--初识异常_第1张图片

       Error类以及他的子类实例代表了JVM本身的错误,错误不能被程序员通过代码处理,很少出现.

       异常:Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件,可以被java异常处理机制使用,是异常处理的核心

总体上我们根据Javac对异常的处理要求,将异常类分为2类。

非检查异常(unckecked exception):Error 和 RuntimeException 以及他们的子类。javac在编译时,不会提示和发现这样的异常,不要求在程序处理这些异常。所以如果愿意,我们可以编写代码处理(使用try…catch…finally)这样的异常,也可以不处理。对于这些异常,我们应该修正代码,而不是去通过异常处理器处理 。这样的异常发生的原因多半是代码写的有问题。如除0错误ArithmeticException,错误的强制类型转换错误ClassCastException,数组索引越界ArrayIndexOutOfBoundsException,使用了空对象NullPointerException等等。

检查异常(checked exception):除了Error 和 RuntimeException的其它异常。javac强制要求程序员为这样的异常做预备处理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch语句捕获它并处理,要么用throws子句声明抛出它,否则编译不会通过。这样的异常一般是由程序的运行环境导致的。因为程序可能被运行在各种未知的环境下,而程序员无法干预用户如何使用他编写的程序,于是程序员就应该为这样的异常时刻准备着。如SQLException , IOException,ClassNotFoundException 等

初识异常:

在 java 中提供了一种解决异常的方式:
try-catch 语句。
语法:
    try{
        //可能产生异常的代码
    }catch(产生的异常的类型  变量名){
        //任意的java 代码。
    }
执行过程:
    1:如果try 中不产生异常。那么try 中的所有的代码都将被执行,跳过 catch ,执行后续的代码。
    2:如果try 中产生了异常,那么从产生异常的位置开始,try 代码块后续的代码都将被跳过,执行catch 中的代码。
        如果在try 代码块中产生了异常对象,如果该异常对象的类型 是 catch 小括号中的异常类型的实例,那么就会执行catch 中的代码。
        否则不会执行。
catch 代码块:
    如果在try 代码块中产生了异常对象,而且该异常对象是 catch 后的异常类型 的实例,那么该异常就被捕获了!
    产生的异常对象将 catch 后的参数变量 实例化。 通过参数变量就可以访问 产生的异常对象了。

实例:

package com.example;

import java. util .Scanner ;

public class AllDemo

{

public static void main (String [] args )

{

System . out. println( "----欢迎使用命令行除法计算器----" ) ;

CMDCalculate ();

}

public static void CMDCalculate ()

{

Scanner scan = new Scanner ( System. in );

int num1 = scan .nextInt () ;

int num2 = scan .nextInt () ;

int result = devide (num1 , num2 ) ;

System . out. println( "result:" + result) ;

scan .close () ;

}

public static int devide (int num1, int num2 ){

return num1 / num2 ;

}

}


运行结果:

/*****************************************


----欢迎使用命令行除法计算器----

0

Exception in thread "main" java.lang.ArithmeticException : / by zero

at com.example.AllDemo.devide( AllDemo.java:30 )

at com.example.AllDemo.CMDCalculate( AllDemo.java:22 )

at com.example.AllDemo.main( AllDemo.java:12 )


----欢迎使用命令行除法计算器----

r

Exception in thread "main" java.util.InputMismatchException

at java.util.Scanner.throwFor( Scanner.java:864 )

at java.util.Scanner.next( Scanner.java:1485 )

at java.util.Scanner.nextInt( Scanner.java:2117 )

at java.util.Scanner.nextInt( Scanner.java:2076 )

at com.example.AllDemo.CMDCalculate( AllDemo.java:20 )

at com.example.AllDemo.main( AllDemo.java:12 )

*****************************************/

异常是在执行某个函数时发生的,而函数有是层级调用,形成调用栈的,因为,只要一个函数发生了异常,那么他所有的caller都会被异常影响,当这些被影响的函数以异常信息输出时,就形成了异常追踪栈.

异常最先发生的地方,叫做异常抛出点:

异常(1)--初识异常_第2张图片

从上面的例子可以看出,当devide函数发生除0异常时,devide函数将抛出ArithmeticException异常,因此调用他的CMDCalculate函数也无法正常完成,因此也发送异常,而CMDCalculate的caller——main 因为CMDCalculate抛出异常,也发生了异常,这样一直向调用栈的栈底回溯。这种行为叫做异常的冒泡,异常的冒泡是为了在当前发生异常的函数或者这个函数的caller中找到最近的异常处理程序。由于这个例子中没有使用任何异常处理机制,因此异常最终由main函数抛给JRE,导致程序终止。

上面的代码不使用异常处理机制,也可以顺利编译,因为2个异常都是非检查异常。但是下面的例子就必须使用异常处理机制,因为异常是检查异常。

代码中我选择使用throws声明异常,让函数的调用者去处理可能发生的异常。但是为什么只throws了IOException呢?因为FileNotFoundException是IOException的子类,在处理范围内。

列:

@Test

public void testException() throws IOException

{

//FileInputStream的构造函数会抛出FileNotFoundException

FileInputStream fileIn = new FileInputStream("E:\\a.txt");


int word;

//read方法会抛出IOException

while((word = fileIn.read())!=-1)

{

System.out.print((char)word);

}

//close方法会抛出IOException

fileIn.clos

}

 

你可能感兴趣的:(javaSE,异常,Exception)