Java Exception
异常的层级:
Checked VS Unchecked Exception
参考:
有两种异常:checked exceptions 和 unchecked exceptions。主要区别是checked exception在编译的时候检查,unchecked exception在运行时检查。
checked exception
checked exception要使用 try-catch
来捕获或者使用throws
关键字来声明,否则的话,程序将会报编译错误。
如下的例子:读取myfile.txt
中的内容并在屏幕上显示,这个程序有3处抛出checked exception
1.FileInputStream
抛出FileNotFoundException
2.read()
方法抛出IOException
3.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
如何解决呢?
1.使用throws
关键字声明异常
public static void main(String args[]) throws IOException, FileNotFoundException
2.使用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 Exceptions
SQLException
IOException
DataAccessException
ClassNotFoundException
InvocationTargetException
unchecked exception
unchecked exception表示如果程序抛出了一个exception,即使你不处理异常,程序也不会报编译错误。所有的unchecked exception都是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 exception
NullPointerException
ArrayIndexOutOfBoundsException
ArithmeticException
IllegalArgumentException
try-catch
参考:
try-catch
的流程:
1.如果try
块中发生了异常,那么对异常的控制就转到了catch
块中。
2.finally
块最终都会执行
多个catch块
class Example2{
public static void main(String args[]){
try{
int a[]=new int[7];
a[4]=30/0;
System.out.println("First print statement in try block");
}
catch(ArithmeticException e){
System.out.println("Warning: ArithmeticException");
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("Warning: ArrayIndexOutOfBoundsException");
}
catch(Exception e){
System.out.println("Warning: Some Other exception");
}
System.out.println("Out of try-catch block...");
}
}
输出结果为:
Warning: ArithmeticException
Out of try-catch block...
嵌套的try-catch
参考:
Each time a try block does not have a catch handler for a particular exception, the stack is unwound and the next try block’s catch (i.e., parent try block’s catch) handlers are inspected for a match.
If no catch block matches, then the java run-time system will handle the exception.
如下的例子:
class Nest{
public static void main(String args[]){
//Parent try block
try{
//Child try block1
try{
System.out.println("Inside block1");
int b =45/0;
System.out.println(b);
}
catch(ArithmeticException e1){
System.out.println("Exception: e1");
}
//Child try block2
try{
System.out.println("Inside block2");
int b =45/0;
System.out.println(b);
}
catch(ArrayIndexOutOfBoundsException e2){
System.out.println("Exception: e2");
}
System.out.println("Just other statement");
}
catch(ArithmeticException e3){
System.out.println("Arithmetic Exception");
System.out.println("Inside parent try catch block");
}
catch(ArrayIndexOutOfBoundsException e4){
System.out.println("ArrayIndexOutOfBoundsException");
System.out.println("Inside parent try catch block");
}
catch(Exception e5){
System.out.println("Exception");
System.out.println("Inside parent try catch block");
}
System.out.println("Next statement..");
}
}
其输出结果为:
Inside block1
Exception: e1
Inside block2
Arithmetic Exception
Inside parent try catch block
Next statement..
要点是:无论何时,如果子try-catch
不能处理异常,那么控制器就会回到父级的try-catch
,如果父级也不能处理,程序就会挂掉。
再看如下的例子:
class NestingDemo{
public static void main(String args[]){
//main try-block
try{
//try-block2
try{
//try-block3
try{
int arr[]= {1,2,3,4};
/* I'm trying to display the value of
* an element which doesn't exist. The
* code should throw an exception
*/
System.out.println(arr[10]);
}catch(ArithmeticException e){
System.out.print("Arithmetic Exception");
System.out.println(" handled in try-block3");
}
}
catch(ArithmeticException e){
System.out.print("Arithmetic Exception");
System.out.println(" handled in try-block2");
}
}
catch(ArithmeticException e3){
System.out.print("Arithmetic Exception");
System.out.println(" handled in main try-block");
}
catch(ArrayIndexOutOfBoundsException e4){
System.out.print("ArrayIndexOutOfBoundsException");
System.out.println(" handled in main try-block");
}
catch(Exception e5){
System.out.print("Exception");
System.out.println(" handled in main try-block");
}
}
}
其输出结果为:
ArrayIndexOutOfBoundsException handled in main try-block
ArrayIndexOutOfBoundsException
出现在try-block3
中,由于block3
没有处理这个异常,那么就交由try-block2
,try-block2
也没有处理这个异常,就交给父try-block
来处理。
用户自定义异常
参考:
使用throw
关键字抛出user-defined
的异常。
例子 1: How to throw your own exception explicitly using throw keyword
package beginnersbook.com;
class MyOwnException extends Exception {
public MyOwnException(String msg){
super(msg);
}
}
class EmployeeTest {
static void employeeAge(int age) throws MyOwnException{
if(age < 0)
throw new MyOwnException("Age can't be less than zero");
else
System.out.println("Input is valid!!");
}
public static void main(String[] args) {
try {
employeeAge(-2);
}
catch (MyOwnException e) {
e.printStackTrace();
}
}
}
输出结果为:
beginnersbook.com.MyOwnException: Age can't be less than zero
例子2: How to throw an already defined exception using throw keyword
package beginnersbook.com;
class Exception2{
static int sum(int num1, int num2){
if (num1 == 0)
throw new ArithmeticException("First parameter is not valid");
else
System.out.println("Both parameters are correct!!");
return num1+num2;
}
public static void main(String args[]){
int res=sum(0,12);
System.out.println(res);
System.out.println("Continue Next statements");
}
}
输出结果为:
Exception in thread main java.lang.ArithmeticException: First parameter is not valid
finally return
参考:
如果在try-catch
中return
,finally
块还会执行吗?
答案是yes,finally
块每次都会执行。唯一的例外是System.exit()
class FinallyDemo
{
public static int myMethod()
{
try {
//try block
return 0;
}
finally {
//finally
System.out.println("Inside Finally block");
}
}
public static void main(String args[])
{
System.out.println(FinallyDemo.myMethod());
}
}
输出结果为:
Inside Finally block
0
finally
块会覆写try-catch
块中返回的结果吗?
会,如下例子:
public static int myTestingFuncn(){
try{
....
return 5;
} finally {
....
return 19;
}
}
返回值为19
其它
1. java.lang.RuntimeException与java.lang.Exception的区别
RuntimeExceptions
可以通过程序来避免,例如NullPointerException
,ArrayIndexOutOfBoundException
。在调用方法之前检查null
,则NullPointerException
就绝不会发生。
参考difference between java.lang.RuntimeException and java.lang.Exception
//Create your own exception class subclassing from Exception
class MyException extends Exception {
public MyException(final String message) {
super(message);
}
}
public class Process {
public void execute() {
throw new RuntimeException("Runtime");
}
public void process() throws MyException {
throw new MyException("Checked");
}
}
2.在catch中return
参考java 异常捕捉 ( try catch finally ) 你真的掌握了吗?
抛出 Exception,当 catch 体里有 return,finally 体的代码块将在 catch 执行 return 之前被执行