1 概述
异常是Java中提供的一种识别及响应错误情况的一致性机制。有效地异常处理能使程序更加健壮、易于调试。
异常发生的原因有很多,比如:
- 用户输入了非法数据
- 要打开的文件不存在
- 网络通信时连接中断
- JVM内存溢出
- 这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。
异常发生的原因很多,尤其是用户输入和要打开的资源不存在
* 这些异常出错后,会导致程序生命周期终止执行,从错误代码开始,之后的代码都不会执行
* java中有一个专门模拟异常的类,就是Throwable,所有异常都继承这个类
2 之前常见的异常
空指针
下标越界
栈内存溢出
类型转换异常
3 继承体系
4 Error
4.1 概述
系统内部错误,这类错误由系统进行处理,程序本身无需捕获处理。
比如:OOM(内存溢出错误)、VirtualMachineError(虚拟机错误)、StackOverflowError(堆栈溢出错误)等,一般发生这种情况,JVM会选择终止程序。
4.2 示例
//堆栈溢出错误
public class TestError {
public static void recursionMethod() {
recursionMethod();// 无限递归下去
}
public static void main(String[] args) {
recursionMethod();
}
}
报错信息:
Exception in thread "main" java.lang.StackOverflowError
at com.TestError.recursionMethod(TestError.java:5)
at com.TestError.recursionMethod(TestError.java:5)
at com.TestError.recursionMethod(TestError.java:5)
at com.TestError.recursionMethod(TestError.java:5)
at com.TestError.recursionMethod(TestError.java:5)
at com.TestError.recursionMethod(TestError.java:5)
... ...
5 Exception
5.1 概述
Exception是所有异常类的父类。分为非RuntimeException和RuntimeException 。
- 非RuntimeException
指程序编译时需要捕获或处理的异常,如IOException、自定义异常等。属于checked异常。 - RuntimeException
指程序编译时不需要捕获或处理的异常,如:NullPointerException等。属于unchecked异常。一般是由程序员粗心导致的。如空指针异常、数组越界、类型转换异常等。
5.2 常用方法
异常处理的两种方式
* 1 throws: 抛出异常,告诉调用处这里可能有什么问题
* 如果你把异常抛给了调用处,那么调用处要么也抛出去,要么解决
* 2 try...catch...: 解决异常
代码如下
//打开资源文件
try{
FileInputStream fiStream=new FileInputStream("D:/xxx");
System.out.println(123);
//}catch(Exception e){
}catch(FileNotFoundException e){
//打印错误的追踪栈帧,比较常用,适合程序员排错
//e.printStackTrace();
//获取错误信息,适合响应给用户
String msg=e.getMessage();
System.out.println(msg);
}
System.out.println(456);
5.3 try...catch...
第一种
语法:try{
* 高风险代码;
* }catch(异常类型 变量){
* 解决方案;
* }
第二种
语法:try{
* 高风险代码;
* }catch(异常类型 变量){
* 处理方案;
* }catch(异常类型 变量){
* 处理方案;
* }...
其中catch中异常类型不能有继承关系,如果有继承关系,需要从子类到父类
第三种
语法: try(开启资源){
* 高风险代码;
* }catch(异常类型 变量){
* 处理措施;
* }
5.4 覆写
代码实现:class A{
public void m1() throws IOException{
}
}
class B extends A{
@Override
//方法覆写,不能比原方法拥有更宽泛的异常
//抛出的异常类可以是父类方法中抛出的类,也可以是对应的子类,但不能是他的父类
//父类抛出一个异常类A,那么子类要么还抛出A,要么抛出A的子类,要么不抛出异常,但是不能是A的父类
public void m1() throws FileNotFoundException {
}
5.5 Throws
throws抛出异常,但并不会处理异常,是一种提醒机制
* 如果调用的方法抛出一个编译时的异常,那么就用try...catch处理掉,或者也抛出
* throws是抛出异常并不会解决异常,一般用于类库端(被调用的这个类)
* 而try...catch...是解决异常的,一般用于客户端(调用其他类的这个类,一般客户端都有main方法)
代码实现:public static void main(String[] args) throws FileNotFoundException{
m1();
}
public static void m1() throws FileNotFoundException{
m2();
}
public static void m2() throws FileNotFoundException{
m3();
}
public static void m3() throws FileNotFoundException{
FileInputStream fis=new FileInputStream("xxx");
}
抛异常,可以同时抛出多个,逗号隔开,没有先后顺序
代码: public static void main(String[] args) throws Exception,FileNotFoundException,IOException{
}
5.6 Finally
5.6.1 使用
finally: 必须执行的语句块, 比如:打开的资源需要关闭
* 1 finally不能单独出现,必须和try一起使用,或者和try...catch...一起使用
* 2 finally语句块只有一种不执行情况,那就是关闭虚拟机 System.exit(0);
5.6.2 注意
finally中的return优先级比较高,所以即使在代码中位置靠后,只要不出现虚拟机关闭的情况,就会优先执行,前面的return在编译的class文件中会被去掉
5.6.3 应用场景
代码实现: FileInputStream fis=null;
try {
//打开资源
fis=new FileInputStream("xxx");
//xxx操作
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
//关闭资源
try {
//判断是否打开资源,如果打开就关闭
if(fis!=null){
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
5.7 Throw
异常源点
Throw new 异常类(错误信息);
参考自定义异常
5.8 自定义异常类
5.8.1 定义
1 继承一个已有的异常类
* 判断是运行时异常还是编译时异常,如果是运行时异常需要继承RuntimeException,否则就继承Exception即可
* 一般情况下我们写的一定是编译时异常
* 2 公共的无参构造
* 3 公共的有参构造,传入字符串,并在构造方法中把该字符串传递给父类
5.8.2 应用场景
public static void login(String username,String password) throws UserException{
if (username.equals("admin")) {
if (password.equals("root")) {
//TODO 登陆成功
//return "登陆成功";
}else{
//TODO密码不正确
//return "密码不正确";
throw new UserException("密码不正确");
}
}else {
//TODO用户名不正确
//return "用户名不正确";
throw new UserException("用户名不正确");
}
}
Scanner scanner=new Scanner(System.in);
System.out.println("请输入用户名和密码:");
String username=scanner.next();
String password = scanner.next();
// System.out.println(username+":"+password);
// String result=UserService.login(username,password);
// if (result.equals("登陆成功")) {
// System.out.println("欢迎回来");
// }else {
// System.out.println(result);
// }
try {
UserService.login(username,password);
System.out.println("登陆成功");
} catch (UserException e) {
//e.printStackTrace();
System.out.println(e.getMessage());
}