前言
异常是程序在 编译 或 执行 的过程中可能出现的问题,语法错误不算在异常体系
提前处理异常,程序会更加安全
一、异常体系
Error:
系统级别问题、JVM退出等,代码无法控制
Exception:
Java.lang包下,称为异常类,它表示程序本身可以处理的问题
Runtime Exception及其子类:
运行时异常,编译阶段不会报错(如空指针,数组索引越界异常)
除Runtime Exception之外所有异常:
编译时异常,编译期必须处理的,否则程序不能通过编译(如日期格式化)
二、 异常示例
1.运行时异常
编译阶段不会报错,运行时才会提示错误
public static void main(String[] args) {
//数组索引越界异常:ArrayIndexOutOfBoundsException
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
//空指针异常:NullPointerException,直接输出没问题,但是调用空指针的变量功能就会报错
String name = null;
System.out.println(name); //可以输出
System.out.println(name.length()); //报错
//类型转换异常:ClassCastException
Object o = 12;
String s = (String) o;
//数学操作异常:ArithmeticException
int c = 10/0;
//数字转换异常:NumberFormatException
String number = "a2";
Integer i = Integer.valueOf(number);
}
2.编译时异常
编译阶段就报错,必须要处理
如下图,日期解析异常
三、异常处理
1.默认异常处理
通常我们不对代码可能出现的异常进行处理,Java就会默认处理我们的异常,如下:
默认会在出现异常的代码处,自动创建一个异常对象:ArithmeticException
异常会从方法中出现的抛给调用者,调用者抛给JVM虚拟机
虚拟机收到异常对象后,先在控制台输出异常栈信息数据
直接从出现异常的地方关闭程序
2.异常处理1 & throws
添加throws ***到方法签名
规范写法 throws Exception
将方法内部出现的异常抛给本方法调用者
throws仅仅是将函数中可能出现的异常向调用者声明,而自己则不具体处理。
throws声明:如果一个方法内部的代码会抛出检查异常(checked exception),而方法自己又没有完全处理掉或并不能确定如何处理这种异常,则javac保证你必须在方法的签名上使用throws关键字声明这些可能抛出的异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理,否则编译不通过。
public static void main(String[] args) throws ParseException {
parseTime("2015-10-10 10:10:10");
}
public static void parseTime(String data) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
Date d = sdf.parse(data);
}
3.异常处理2 & try . . . catch . . .
监视捕获异常,用在方法内部,可以将方法内部出现的异常直接捕获处理
发生异常的方法自己独自完成异常处理,程序还能继续往下执行
public static void main(String[] args) {
parseTime("2015-10-10 10:10:10");
}
public static void parseTime(String data) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
Date d = sdf.parse(data);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
4.异常处理3 & 前面两者的结合
方法将异常通过throws抛给调用者,调用者收到异常后捕获处理。
public static void main(String[] args) {
try {
parseTime("2015-10-10 10:10:10");
System.out.println("成功");
} catch (ParseException e) {
e.printStackTrace();
System.out.println("失败");
}
}
public static void parseTime(String data) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
Date d = sdf.parse(data);
}
5.运行时异常的处理
可以不进行处理,编译阶段不会报错,但建议处理,在最外层捕获
public static void main(String[] args) {
System.out.println("开始");
try {
int d = 10/0;
} catch (Exception e) {
throw new RuntimeException(e);
}
System.out.println("结束");
}
四、自定义异常
JAVA无法为所有的问题提供异常类,如果企业想通过异常的方式来管理某个业务问题,就需要自定义异常类了。
按照国际惯例,自定义的异常应该总是包含如下的构造函数:
一个无参构造函数
一个带有String参数的构造函数,并传递给父类的构造函数。
一个带有String参数和Throwable参数,并都传递给父类构造函数。
一个带有Throwable 参数的构造函数,并传递给父类的构造函数。
注意: 如果自定义异常是为了提示,在使用的时候,一定要用try..catch,不要直接用throw往外抛。
自定义编译时异常
定义一个异常类继承Exception
重写构造器
public class Ageilleagaleception extends Exception{
public Ageilleagaleception (){
}
public Ageilleagaleception(String message){
super(message);
}
}
在出现异常的地方用throw new自定义对象抛出
public static void checkAge(int age) throws Ageilleagaleception {
if(age < 0 || age > 200){
throw new Ageilleagaleception(age+"is illegal");
}else {
System.out.println("年龄正确");
}
}
自定义运行时异常
定义一个类继承RuntimeException
重写构造器
在出现异常的地方用throw new自定义对象抛出
总结
程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常
异常处理不能替代简单的测试,不要过分的细化异常