之前学习C#这门语言,接触过“异常”这个名词,那个时候自己理解为程序非正常执行,包括参数传递异常,程序处理数据异常等;为了防止出错导致程序异常卡死,所以此时通过throw关键字将错误抛出,至于抛出到哪里以及抛出过程当时真的不清楚。这里推荐一篇博客关于C#异常过程-C#异常处理总结和C#异常执行原理。
现在学习了Java中的异常处理后,发现当时直接throw new Exception真的挺有意思,这个Exception应该是所有错误的父类,类似于Object类一样;今天咱们就一块来看看Java中的异常究竟是怎么回事,同时又如何处理。
异常:
程序执行过程中,出现非正常的情况,最终会导致JVM的非正常停止。而且了解了异常本身就是一个类,只不过程序非正常执行的过程中会创建异常对象并抛出一个异常对象,JRE(自我感觉就是C#中的CLR)异常处理程序来处理异常;没错,我其实应该早就想到了;Java处理异常的方式就是中断。
Java中异常的根类:
java.lang.Throwable,而且有两个子类java.lang.Error和java.lang.Exception。前者需要避免,而后者是由于执行不当导致的,所以只能修复。今天所讲的Exception类中包含两个,其一编译时期异常(IOException等),另外一个是运行时期的异常(RuntimeException);前者必须进行处理,后者可以进行容错,保证程序不会因为异常而终止即可。
异常对象产生步骤:
调用方法([传参]),然后发生异常(名称,内容,位置),将这些信息封装到异常对象中;JVM会将产生的异常抛给调用者;
调用者方法接收到异常对象后,如果没有进行异常处理的话,会继续把异常抛给JVM;JVM将异常对象名称、内容、位置显示到屏幕中;同时程序终止执行。
调用者方法处理过程:
在Java中提供了一个关键字Throw,用来抛出一个指定的异常对象。至于这个异常对象该如何实例化,还需要提前测试咱们这里会产生什么样的异常对象,对症下药;既然我们将错误抛出了,那么调用者该如何处理呢?一种方式是进行捕获处理,另外一种就是继续将问题声明出去,使用throws声明处理。
那么此时我们需要在存在异常方法进行声明异常类型,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常)。那么try..catch便派上用场了;该语句可以通过捕获异常,对出现的异常信息进行指定方式处理。
说白了就是这样:
1:测试过程中感觉某段代码执行会出现什么类型的异常;
2:收集异常,在该方法中进行try...catch处理;
3:如果不知道这段程序产生什么样的异常,或者如何处理的话,此时交给调用者方法进行处理;然后在调用者方法里面进行try...catch处理即可。 注意:自定义异常类的话,继承Exception编译期异常类;如果不在自身方法中进行try...catch处理的话,就必须将该异常声明给调用者。反之继承RuntimeException运行时期异常类;无论自身是否处理,都不需要将该异常声明给调用者。
打印异常信息包含名称、内容、位置:
public String getMessage(); //获取异常的描述信息,也就是错误原因,反馈给用户。
public String toString(); //获取异常的类型和异常描述信息(一般不用)。
public void printStackTrace(); //打印异常的跟踪信息并输出到控制台;包含了异常的类型,异常原因,以及异常出现的位置。
理论转实战:
描述了这么多关于异常的事情,那么异常类究竟是谁产生的?没错就是JDK,但是只要是预先设定的,肯定有不符合人为意愿的存在情况,此时我们就要自定义异常类。
//自定义异常处理类RegisterException
public class RegisterException extends Exception {
/**
* 空参构造
*/
public RegisterException() {
}
/**
*
* @param message 表示异常提示
*/
public RegisterException(String message) {
super(message);
}
}
//模拟从数组中检测是否存在方法中参数的数值
public class Demo {
private static String[] names = {"bill","hill","jill"};
public static void main(String[] args) {
//调用方法,处理异常
try{
// 可能出现异常的代码
checkUsername("nill");
System.out.println("注册成功");//如果没有异常就是该用户已存在
}catch(RegisterException e){
//处理异常
e.printStackTrace();
}
}
//判断当前注册账号是否存在
//注意:因为自定义RegisterException继承自Exception,是编译期异常;所以如果自身不进行处理的话,那么就必须声明异常类型。
public static boolean checkUsername(String uname) throws RegisterException{
for (String name : names) {
if(name.equals(uname)){//如果名字在这里面 就抛出登陆异常
throw new RegisterException("亲"+name+"已经存在了!");
}
}
return true;
}
}