异常
Java当中对可能出现异常或者错误的的一种描述、信息的对象体现
异常的分类
Throwable
Error: 我们无法处理,例如 内存溢出
Exception: (受检异常) Exception或者Exception的子类但不是RuntimeException的子类称为编译时异常
RuntimeException (运行时异常 非受检异常) RuntimeException或者RuntimeException的子类
异常处理的目的: 能够让程序继续执行,同时打印错误信息\
JVM处理异常的方式
1.打印错误信息
2.终止程序
JVM处理异常不能够满足我们的需求,所以需要自己处理异常
处理异常的方式
1.try…catch…finally
2.throws
处理方式的格式:
try {
可能处理出现问题的代码
} catch(异常类名 异常对象) {
异常发生后的处理方式
} catch(异常类名 异常对象) {
异常发生后的处理方式
} ...
异常处理的执行流程
1.程序执行到 System.out.println(a / b);代码
2.系统会抛出一个异常对象
创建一个异常对象,并且抛出给开发者
ArithmeticException e = new ArithmeticException(“/ by zero”);
throw e;
3.代码进入catch块进行匹配
Exception ae = e; // 多态
4.匹配成功: 程序会转入catch块执行
匹配失败: 程序交还给JVM处理
注意事项:
1.如果程序在try块中出现了异常,那么无论try块下面有多少行代码都不会被执行,执行去和catch块进行匹配
2.异常处理的标准格式
a.能够显示处理的尽量显示处理,提高程序的可读性
b.程序的最后面一定要加上Exception作为父类接受一切异常,提高了程序的健壮性
代码示例
public static void main(String[] args) {
System.out.println("游戏开始");
int a = 10;
int b = 0;
String s = null;
int[] arr = new int[3];
Object obj = "张三";
try {
// System.out.println(a / b);
// System.out.println(s.equals("abc"));
// arr[4] = 10;
Integer integer = (Integer) obj;
} catch(ArithmeticException ae) {
// System.out.println("出问题了,除数为0!");
ae.printStackTrace();
} catch(NullPointerException ae) {
// System.out.println("出问题了,对象不能够为null!");
ae.printStackTrace();
} catch(ArrayIndexOutOfBoundsException aioobe) {
// System.out.println("出问题,数组越界");
aioobe.printStackTrace();
} catch (Exception e) {
// System.out.println("有问题");
e.printStackTrace();
}
System.out.println("游戏结束");
}
}
Throwable类
1. 该类是所有异常和错误的超类
2. 只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出
3. 只有此类或其子类之一才可以是 catch 子句中的参数类型
异常链
Throwable initCause(Throwable cause)
将此 throwable 的 cause 初始化为指定值。
Throwable getCause()
返回此 throwable 的 cause;如果 cause 不存在或未知,则返回 null
常用方法
Throwable fillInStackTrace() 填充错误信息到堆栈中
Throwable getCause()
返回此 throwable 的 cause;如果 cause 不存在或未知,则返回 null。
String getLocalizedMessage() 获取错误信息 detailMessage
String getMessage() 同上
StackTraceElement[] getStackTrace() 获取堆栈中的错误信息
Throwable initCause(Throwable cause)
将此 throwable 的 cause 初始化为指定值。
void printStackTrace() 输出错误信息到控制台
void printStackTrace(PrintStream s)
void printStackTrace(PrintWriter s)
输出错误信息到 外界 【浏览器 文件 …】
void setStackTrace(StackTraceElement[] stackTrace)
设置将由 getStackTrace() 返回,并由 printStackTrace() 和相关方法输出的堆栈跟踪元素。
String toString() 获取错误类的对象描述 类路径: 错误信息
返回此 throwable 的简短描述。
StackTraccElement 中的常见方法
String getClassName()
返回类的完全限定名,该类包含由该堆栈跟踪元素所表示的执行点。
String getFileName()
返回源文件名,该文件包含由该堆栈跟踪元素所表示的执行点。
int getLineNumber()
返回源行的行号,该行包含由该堆栈该跟踪元素所表示的执行点。
String getMethodName()
返回方法名,此方法包含由该堆栈跟踪元素所表示的执行点。
int hashCode()
返回此堆栈跟踪元素的哈希码值。
boolean isNativeMethod()
如果包含由该堆栈跟踪元素所表示的执行点的方法是一个本机方法,则返回 true。
throws关键字
应用场景:
1.我处理不了
2.我没有权限处理
3.我不想处理
格式:
[修饰符] 返回值类型 方法名(参数列表) [throws 异常类1,异常类2…]{
}
1.该方法抛出异常类,表示抛出调用者处理,谁调用谁处理
2.一个方法可以抛出多个异常
3.如果一个方法抛出的是一个编译时异常,那么必须处理,调用者也必须处理
4.子类继承父类,重写方法,抛出的异常不能够被扩大
代码示例
public static void main(String[] args) /*throws ArithmeticException */{
System.out.println("Start");
/*try {
method();
} catch (Exception e) {
e.printStackTrace();
}*/
try {
show();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("End");
}
public static void show() throws ParseException {
DateFormat df = new SimpleDateFormat("yyyy");
df.parse("1997");
}
public static void method() throws ArithmeticException, NullPointerException {
test();
}
public static void test() throws ArithmeticException, NullPointerException {
int a = 10;
int b = 0;
System.out.println(a / b);
}
}
class Father {
public void show() throws NullPointerException {
}
}
class Son extends Father {
@Override
public void show() throws NullPointerException {
}
}
throw
throw 和 throws的区别
1.throws是在方法的声明上,throw在方法体内
2.throws表示异常出现的一种可能性,throw表示一定出现了异常
3.throws表示声明的是异常类,而throw抛出的是异常对象
4.throws可以抛出多个异常类,而throw只能够抛出一个异常对象
代码示例
public static void main(String[] args) throws ParseException {
System.out.println("start");
try {
method();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("end");
}
public static void method() throws ArithmeticException {
int a = 10;
int b = 0;
// 处理方式 一: 规避异常
/*if (b != 0) {
System.out.println(a / b);
}*/
// 处理方式二: 直面异常
if (b == 0) {
// ArithmeticException ae = new ArithmeticException("兄弟,除数不能为0你不知道啊!");
throw new ArithmeticException("兄弟,除数不能为0你不知道啊!");
}
System.out.println(a / b);
}
}
finally
finally修饰的代码块一定会被执行,除非在执行到finally之前程序异常退出或者调用了系统退出的方法。
finally用于释放资源,在IO流操作和数据库操作中会见到。
代码示例
public static void main(String[] args) {
int a = 10;
int b = 0;
try {
System.out.println(a / b);
} catch (Exception e) {
e.printStackTrace();
// return;
System.exit(0);
} finally {
// 一般用来释放资源
System.out.println("finally代码块被执行");
}
System.out.println("over");
}
}
自定义异常
JDK中提供的异常不能够完全满足开发的时候,比如分数在0~100分之外就算异常
这个异常JDK中没有,需要自定义异常
代码示例
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入分数: ");
Double score = input.nextDouble();
try {
System.out.println(isLegalScore(score)? "合法":"不合法");;
} catch (ScoreException e) {
e.printStackTrace();
} finally {
if (input != null) {
input.close();
}
}
System.out.println("批改结束....");
}
/*
* 判断分数是否在0~100分之间
*/
public static boolean isLegalScore(Double score) throws ScoreException {
if (score < 0 || score > 100) {
throw new ScoreException("兄弟,这个分数是不是改错了!这个" + score + "不行,0~100分之间才可以,例如61分,79分");
}
return true;
}
}
class ScoreException extends Exception {
private static final long serialVersionUID = -1989349702073875392L;
public ScoreException() {}
public ScoreException(String message) {
super(message);
}
运行结果: