有两种类型的异常:一种是checked异常一种是unchecked异常,在这篇文章中我们将利用实例来学习这两种异常,checked的异常和unchecked异常最大的区别就是checked去唱是在编译时检查的而unchecked异常是在运行时检查的。
什么是checked异常呢?
checked异常在编译时检查,这意味着如果一个方法抛出checked异常,那么它应该使用try-catch块或者使用throws关键字来处理这个异常,否则的话程序会报编译错误,命名为checked异常是因为是在编译时checked的。
用例子来理解这个问题,在这个例子中,我们读取myfile.txt这个文件并且将它的内容输出到屏幕上,在下边这个程序中有三处异常被抛出。FileInputStream使用了指定的文件路径和名称,抛出FileNotFoundException,这个读取文件内容的read()函数抛出IOException异常,关闭文件输入流的close()函数同样也抛出IOException异常。
import java.io.*;
class Example {
public static void main(String args[])
{
FileInputStream fis = null;
/*This constructor FileInputStream(File filename)
* throws FileNotFoundException which is a checked
* exception*/
fis = new FileInputStream("B:/myfile.txt");
int k;
/*Method read() of FileInputStream class also throws
* a checked exception: IOException*/
while(( k = fis.read() ) != -1)
{
System.out.print((char)k);
}
/*The method close() closes the file input stream
* It throws IOException*/
fis.close();
}
}
输出的结果:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
Unhandled exception type FileNotFoundException
Unhandled exception type IOException
Unhandled exception type IOException
为什么这个会编译错误呢?像我在一开始提到的checked异常在编译时被检查,因为我们没有处理这些异常,我们的编译程序报出了编译错误。
怎么解决这个错误呢?有两种方式避免这种错误,我们一条一条的来看:
方法一:使用throws关键字声明异常
我们知道在main()函数里有三个checked异常发生,那么避免这种编译错误的一种方式就是:在方法上使用throws关键字声明一个异常,你或许会想我们的代码抛出FileNotFoundException和IOEXception,为什么我们是声明了一个IOException呢,原因是IOException是FileNotFoundException的父类,前者默认覆盖了后者,如果你想你也可以这样声明异常:
public static void main(String args[]) throws IOException, FileNotFoundException.
import java.io.*;
class Example {
public static void main(String args[]) throws IOException
{
FileInputStream fis = null;
fis = new FileInputStream("B:/myfile.txt");
int k;
while(( k = fis.read() ) != -1)
{
System.out.print((char)k);
}
fis.close();
}
}
输出结果:
File content is displayed on the screen.
方法二:使用try-catch块处理异常
上一种方法并不是很好,那不是处理异常最好的方式,你应该对每一个异常给出有意义的信息,使那些想了解这些错误的人能够理解,下边是这样的代码:
import java.io.*;
class Example {
public static void main(String args[])
{
FileInputStream fis = null;
try{
fis = new FileInputStream("B:/myfile.txt");
}catch(FileNotFoundException fnfe){
System.out.println("The specified file is not " +
"present at the given path");
}
int k;
try{
while(( k = fis.read() ) != -1)
{
System.out.print((char)k);
}
fis.close();
}catch(IOException ioe){
System.out.println("I/O error occurred: "+ioe);
}
}
}
上边的代码能够正常运行,并将内容显示出来
下边是一些其他的checked异常
SQLException
IOEXception
DataAccessException
ClassNotFoundException
InvocationTargetException
什么是unchecked异常呢
unchecked异常在编译时不会检查,这意味着即使你没有声明或者处理异常你的程序也会抛出一个unchecked异常,程序不会给出一个编译错误,大多数情况下这些异常的发生是由于用户在交互过程中提供的坏数据。这需要程序员提前去判断这种能够产生这种异常的情况并且恰当的处理它。所有的unchecked异常都是RuntimeException的子类。
我们来看一下下边的代码:
class Example {
public static void main(String args[])
{
int num1=10;
int num2=0;
/*Since I'm dividing an integer with 0
* it should throw ArithmeticException*/
int res=num1/num2;
System.out.println(res);
}
}
如果你编译这段代码,这段代码将会被通过,但是当你运行的时候它将抛出ArithmeticException。这段代码清楚的表明了unchecked异常在编译期间是不会被checked的,他们在运行期间被检查,我们来看另一个例子:
class Example {
public static void main(String args[])
{
int arr[] ={1,2,3,4,5};
/*My array has only 5 elements but
* I'm trying to display the value of
* 8th element. It should throw
* ArrayIndexOutOfBoundsException*/
System.out.println(arr[7]);
}
}
这段代码同样被成功的编译通过,因为ArrayIndexOutOfBoundsException是unchecked异常。
注意:这并不意味着编译器不检查这些异常我们就不处理这些异常了,事实上我们需要更加小心的处理这些异常,例如在上边的例子中,应该提供给用户一个他想读取的信息在数组中不存在的信息,以便用户修改这个问题
class Example {
public static void main(String args[])
{
try{
int arr[] ={1,2,3,4,5};
System.out.println(arr[7]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("The specified index does not exist " +
"in array. Please correct the error.");
}
}
}
这里还有其他的一些常见的unchecked异常:
NullPointerException
ArrayIndexOutOfBoundsException
ArithmeticException
IllegalArgumentException