一、异常介绍
Exception是异常的英文,也是java.lang包下面的一个类,使用时不用导入。
java.langException继承自Throwable类。Throwable类有2个子类:Error,Exception其中,Error不进行处理,java中只处理异常Exception。
Exception是java中所有异常的父类、根类,java中所有的异常类都直接或间接的继承自Exception类。
1、java中异常有两大类:
(1)CheckedException(又叫非RuntimeException)
继承了Exception类的所有异常中,除了继承自运行时异常外的异常都是非运行时异常。
(2)Unchecked Exception(又叫RuntimeException运行时异常)
java中的运行时异常都直接或间接的继承自RuntimeException类。
2、Exception的处理方法
(1)运行时异常RuntimeException的处理方法
运行时异常可做异常处理,也可以不做处理,推荐不做处理。
有个常出现的运行时异常:NullPointerException
NullPointerException的意思是空指针异常,出现该异常的原因是某个引用为null,但却调用了此引用的某个方法。
(2)非运行时异常
对于非运行时异常必须要对其进行处理,处理方式有两种:第一种是使用try...catch...finally进行捕获;第二种是在调用了会产生异常方法的方法声明处进行抛出异常处理(throws Exception)。
if()
{
}
catch(Exception e)
{
}
finally
{
}
若if语句中遇到异常,则会继续执行catch语句,捕获异常;若if语句未出现异常,则不会处理catch语句;无论如何,finally中的语句一定会被执行,finally语句执行完后会继续执行下面的语句。
public class ExceptionTest
{
public void Method() throws Exception//告诉其他调用此方法的方法,要处理异常
{
throw new MyException();//此处会抛出一个异常,那么在方法声明处也必须进行异常处理
}
public static void main(String args[]) throws Exception//由于调用了Method方法,此处也要处理异常
{
ExceptionTest test = new ExceptionTest();
test.Method();
}
}
二、自定义异常
1、自定义异常的设计思路
所谓自定义异常,通常是定义了一个继承了Exception的子类。一般情况下,在定义时会直接继承Exception类,而不会去继承运行时异常类(RuntimeException)。
2、设计要点
(1)在使用自定义的异常时,必须要进行异常处理,可以进行抛出异常处理,也可以利用if...catch...finally捕获异常;
(2)若同时自定义了多个异常,则可利用多个catch块进行捕获,也可抛出异常。catch块是有顺序的,如果两个异常是子类和父类的关系,则父类的异常必须放在子类异常的后面;否则,若父类异常放在了子类异常的前面,则通过多态,所有异常都会在父类异常catch快中捕获,而没有机会去执行子类异常的catch块,程序编译会报错。
例如:
catch(Exception e)
{
e.printStackTrace();
}
catch(MyException1 e)
{
e.printStackTrace();
}
catch(MyException2 e)
{
e.printStackTrace();
}
这样会报错,Exception的catch块必须放置在MyException1和MyException2的catch块之后。
catch(MyException1 e)
{
e.printStackTrace();
}
catch(MyException2 e)
{
e.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
当然,也可以只用Exception的catch块,因为Exception是所有异常的父类。
catch(Exception e)
{
e.printStackTrace();
}
若两个异常没有关系,则可以随便放置,例如MyException1和MyException2的catch块可以调换顺序,而无影响。
3、示例
package com.lpp.exception;
@SuppressWarnings("serial")
public class MyException1 extends Exception
{
@SuppressWarnings("unused")
private String str;
public MyException1()
{
}
public MyException1(String str)
{
System.out.println(str);
}
}
(2)MyException2异常定义
package com.lpp.exception;
@SuppressWarnings("serial")
public class MyException2 extends Exception
{
@SuppressWarnings("unused")
private String str;
public MyException2()
{
}
public MyException2(String str)
{
System.out.println(str);
}
}
(3)调用异常
package com.lpp.exception;
public class ExceptionTest
{
public void string(String str) throws Exception
{
if(null == str)
{
throw new MyException1("str不能为空");
}
else if("hello".equals(str))
{
throw new MyException2("str不能为hello");
}
else
{
System.out.println(str);
}
}
public static void main(String[] args)
{
ExceptionTest test = new ExceptionTest();
try
{
String str = null;
test.string(str);
}
catch(MyException1 e)
{
e.printStackTrace();
}
catch(MyException2 e)
{
e.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
System.out.println("OK");
}
}
}
结果:
str不能为空
com.lpp.exception.MyException1
at com.lpp.exception.ExceptionTest.string(ExceptionTest.java:9)
at com.lpp.exception.ExceptionTest.main(ExceptionTest.java:26)
OK
三、常见的异常面试问题
1、示例
public class ReturnException
{
public static void main(String[] args)
{
try
{
System.out.println("try");
return;
}
catch (Exception e)
{
System.out.println("catch");
e.printStackTrace();
}
finally
{
System.out.println("finally");
}
System.out.println("ok");
}
}
结果:
try
finally
总结:如果try块中存在return语句,则会先处理finally块(finally块外面的代码将不执行),然后方法再返回。
2、示例
public class ReturnException
{
public static void main(String[] args)
{
try
{
System.out.println("try");
System.exit(0);;
}
catch (Exception e)
{
System.out.println("catch");
e.printStackTrace();
}
finally
{
System.out.println("finally");
}
System.out.println("ok");
}
}
结果:
try
总结:如果try块中存在System.exit(0)语句,则不会执行finally中的代码,因为System.exit(0)会终止当前运行的java虚拟机,程序会在虚拟机终止前结束执行。