程序运行时发生的不被期望的事件,他阻止了程序按照程序员预期正常执行,这就是异常
Throwable为异常的顶级父类
Error和Exception为Throwable的子类:
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都会被异常影响,当这些被影响的函数以异常信息输出时,就形成了异常追踪栈.
异常最先发生的地方,叫做异常抛出点:
从上面的例子可以看出,当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
}