异常机制是指当程序出现错误后,程序如何处理。 当异常抛出后,会发生以下几件事。首先,同Java中创建其他对象一样,将使用new在堆上创建异常对象。 然后,当前的执行路径被终止,并且从当前环境中弹出对异常对象的引用,此时,异常处理机制接管程序。 并开始寻找一个恰当的地方来继续执行程序。
例如,在parseInt的源码中,如果s为空,会抛出一个NumberFormatException异常。
public static int parseInt(String s, int radix)throws NumberFormatException{
if (s == null) {
throw new NumberFormatException("null");
}
...
}
public static void main(String[] args){
String s=null;
Integer.parseInt(s);
System.out.println("**********end**********");
}
如果执行以上代码,程序会打印以下内容:
Exception in thread "main" java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:454)
at java.lang.Integer.parseInt(Integer.java:527)
at com.test.exception.TestException.main(TestException.java:14)
我们并未对这个异常做任何处理,控制台的东西并不是我们打印的,而且这些内容一般是在调用了printStackTrace()方法之后才会打印到控制台的,这就说明JVM抛出了这个异常。并且把它打印到了控制台。
当然我们也可以自己去处理这个异常,处理异常的结果是程序虽然出错了,但是还能往下执行。
public static void main(String[] args) {
try {
String s = null;
Integer.parseInt(s);
System.out.println("**********start**********");
} catch (Exception e) {
e.printStackTrace(System.out);
}
System.out.println("**********end**********");
}
// 输出以下内容
java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:454)
at java.lang.Integer.parseInt(Integer.java:527)
at com.test.exception.TestException.main(TestException.java:13)
*********************end*********************
Exception e 这个参数可以接收到程序抛出的异常对象。
为了区别于JVM自行处理的异常,我们接受到异常的对象之后,把输出重定向到系统的标准输出中。并且程序还在往下执行。但是像这类异常,我们一般不会手动去捕获。
通过上面的案例,可以发现,虽然 parseInt()这个方法可能抛出异常,但是不用try-catch也能直接调用这个方法。
再看一个案例:
// 编译通不过
File file = new File("d:/file.txt");
InputStream inputStream = new FileInputStream(file);
//源码
public FileInputStream(File file) throws FileNotFoundException {
...
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
}
FileInputStream 的源码中也可能会抛出异常,但是如果在外层不加上try-catch编译就会通不过。这就说明这个异常是需要我们自行去处理的。
Exception
RuntimeException
IllegalArgumentException
NumberFormatException
Exception
IOException
FileNotFoundException
原因就在于NumberFormatException继承了RuntimeException,继承自RuntimeException的异常通常被称为不受检查的异常。
以下是jdk源码中对RuntimeException的说明:
* {@code RuntimeException} is the superclass of those
* exceptions that can be thrown during the normal operation of the
* Java Virtual Machine.
RuntimeException是在Java虚拟机正常运行期间可以抛出的那些异常的超类。
RuntimeException这种异常属于错误,将会被自动捕获。所以在调用parseInt()方法时不需要加上try-catch,而其他类型的异常的处理都是由编译器强制实施的,例如使用FileInputStream如果不处理异常,编译就通不过。究其原因,RuntimeException属于编程错误,比如从控制范围之外传递进来的null引用,典型的NullPointerException空指针异常就继承自RuntimeException,属于运行时的异常。