1 异常的基本概念
什么是异常,在程序运行过程中出现的错误,称为异常。
int a = 10;
int b = 0;
int c = a / b;
//error:ArithmeticException
System.out.println(c);
Java给我们提供了这样一个体系结构,当出现问题的时候,它会告诉我们,并且把错误的详细信息也告诉我们了,这就是异常的体系结构,这样我们的程序更健壮,我们可以把这个信息,再进行处理以下告诉用户。
public class ExceptionTest02 {
public static void main(String[] args) {
ArithmeticException ar = new ArithmeticException("算术异常");
System.out.println(ar);
NullPointerException nu = new NullPointerException("空指针异常");
System.out.println(nu);
}
}
运行结果:

以上程序可以看出Java 异常都是类,在异常类中会携带一些信息给我们,我们可以通过这个类把信息取出来。
2 异常的分类
异常主要分为:错误、一般性异常(受控异常)、运行期异常(非受控异常)
错误:如果应用程序出现了 Error,那么将无法恢复,只能重新启动应用程序,最典型的Error 的异常是:OutOfMemoryError
受控异常:出现了这种异常必须显示的处理,不显示处理Java程序将无法编译通过
非受控异常:此种异常可以不用显示的处理,例如被0 除异常,Java没有要求我们一定要处理
3 异常的处理
第一种:在方法声明的位置上,使用throws关键字,抛给上一级。
第二种:使用try…catch语句进行异常的捕捉。
注意:Java中异常发生之后如果一直上抛,最终抛给了main方法,main方法继续上抛,抛给了调用者JVM,JVM知道这个异常发生,只有一个结果。终止Java程序的执行。
public static void main(String[] args) {
//程序执行到此发生ArithmeticException异常
//底层new出了ArithmeticException的异常对象
//然后抛出了,由于是main方法调用的,所以这个异常抛给了main方法
//main方法没有处理,将这个异常抛给了JVM
//jvm最终终止程序的执行
System.out.println(100 / 0);
//这里的hello world没有执行
System.out.println("hello world");
}
public static void main(String[] args) {
//error:出现了ClassNotFoundException未处理
//doSome();
}
public static void doSome() throws ClassNotFoundException{
System.out.println("doSome!!!");
}
//第一种throws,抛出异常
public static void main(String[] args) throws ClassNotFoundException {
doSome();
}
//第二种:try..catch进行捕捉
public static void main(String[] args) {
try {
doSome();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
在开发过程中,处理编译时异常,应该上报还是捕捉呢,怎么选?
如果希望调用者来处理,选择throws上报。
其他情况使用捕捉的方式。
异常中常用的方法:getMessage 和 printStackTrace()
取得异常描述信息:getMessage()
public static void main(String[] args) {
NullPointerException nu = new NullPointerException("空指针异常");
String msg = nu.getMessage();
System.out.println(msg);//空指针异常
}
取得异常的堆栈信息(比较适合于程序调试阶段):printStackTrace();
//java.lang.NullPointerException: 空指针异常
// at ExceptionTest04.main(ExceptionTest04.java:7)
nu.printStackTrace();
关于try…catch中的finally子句:
在finally子句中的代码是最后执行的,并且是一定会执行的,即使try语句块中的代码出现了异常。
finally子句必须和try一起出现,不能单独编写。
finally 在任何情况下都会执行,通常在finally 里关闭资源。
try和finally,没有catch也是可以的。(try)不能单独使用
finally面试题:
public static void main(String[] args) {
System.out.println(m());//100
}
public static int m() {
int i = 100;
try {
//这行代码出现在int i = 100;的下面,所以最终结果必须是返回100
return i;
} finally {
i++;
}
}
Java中规定:
方法体中的代码必须遵循自上而下顺序依次执行。
return语句一旦执行,整个方法必须结束。
final finally finalize有什么区别
final是一个关键字。表示最终的,不变的
finally也是一个关键字,和try联合使用,使用在异常处理机制中,在finally中的代码一定会执行。
finalize()是Object类中的一个方法,作为方法名出现,所以finalize是一个标识符。
4 自定义异常
第一步:编写一个类继承Exception或者RuntimeException。
第二步:提供两个构造方法,一个无参数的,一个带有String参数的。
public class MyException extends Exception {
public MyException() {
}
public MyException(String s) {
super(s);
}
}
class Test {
public static void main(String[] args) {
MyException e = new MyException("用户名不能为空");
e.printStackTrace();
}
}
运行结果:

示例:自定义异常,提示用户名不合法
public class MyException extends Exception{
public MyException(){
}
public MyException(String s){
super(s);
}
}
public class BankRegist {
public void regist(String username,String userpwd) throws MyException {
if (null == username || username.length()<6 ||username.length()>12){
throw new MyException("用户名不合法");
}else {
System.out.println("欢迎您,"+username);
}
}
}
public class BankTest {
public static void main(String[] args) {
BankRegist p = new BankRegist();
try {
p.regist("jack","123");
} catch (MyException e) {
e.printStackTrace();
}
}
}