什么时候使用异常
Throwable
Error 错误 无法专门处理
Exception 异常
受检异常 编译的时候,必须处理的异常,可以使用try-catch捕获异常,也可以通过throws在方法中声明抛出异常
非受检异常(运行时异常)
try-catch-finally
catch可以有多个,catch和finally至少存在一个
如果代码出现异常,异常代码后的代码不再执行,直接跳转到对应的catch代码块进行操作
不管代码是否有异常,finally中的逻辑都会执行,哪怕使用了return (使用System.exit() 退出程序,finally中代码不会执行)
package com.qfedu.exception;
public class App2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a = 10;
int b = 0;
// 针对可能出异常的代码使用try包起来
// 如果出异常,使用catch捕获异常
// 出现异常后,出现异常的代码,后续的代码不会执行,跳转到catch语句块,执行其中的代码
// 如果try括住的代码正常执行,不会进行catch代码块
// 可以写多个catch 捕获不同的异常,如果代码发生异常,和catch后的异常进行比对,
// 符合哪个具体的异常就进入哪个catch代码块中
// 针对需要具体处理的异常,通过在catch后这是具体的异常可以捕获,但是我们不可能预见所以可能的异常,
// 这时,就可以使用catch捕获Exception类型的异常,防止遗漏
// 注意:父类的Exception异常一定要放在所有catch代码块的最后
// 实际开发中,一般报异常了,会将异常信息记录到日志系统
try {
int c = a / b;
System.out.println(c);
// String str = null;
String str = "hello";
System.out.println(str.length());
// ClassCastException
Object o = "hello";
Integer i = (Integer)o;
} catch(ArithmeticException e) {
System.out.println("除0错误");
} catch(NullPointerException e) {
System.out.println("空指针异常");
} catch(Exception e) {
// 打印异常的栈跟踪信息
e.printStackTrace();
System.out.println("未知异常");
}
}
}
package com.qfedu.exception;
public class App4 {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 不管代码是否异常,最终都会执行finally代码块中逻辑
// 在try或catch的代码块中,即使使用了return,finally代码块中的逻辑也会执行
// 使用System.exit()情况下,退出整个程序,finally中逻辑不会执行
try {
int a = 10 / 3;
System.out.println(a);
// return;
// 退出程序
// System.exit(0);
} catch (Exception e) {
System.out.println(e.getMessage());
return;
} finally {
System.out.println("finally");
}
// 了解
// 语法上catch可以不写,如果不写,无法捕获异常,异常就会自动往上层抛,本例中,抛给jvm进行处理
try {
int b = 10 / 0;
} finally {
System.out.println("finally2");
}
}
}
声明方法时,通过throws指定抛出的异常
在方法中,通过throw抛出异常
package com.qfedu.throwes;
public class App {
public static void main(String[] args) {
// TODO Auto-generated method stub
// main方法中调用test1() 方法,
// test1()没有捕获异常并处理,当test1()发生异常时,将异常对象往上抛
// 本例中,test1()中发生的异常抛给main()方法
// main()中也没有捕获异常进行处理,main()方法将异常继续往上抛,最终抛给jvm,由jvm处理异常
// test1();
try {
// test2();
test3();
} catch(ArithmeticException e) {
System.out.println(e.getMessage());
} catch(Exception e) {
System.out.println("未知异常");
}
}
public static void test1() {
int a = 10 / 0;
System.out.println(a);
}
// 在方法中,声明需要抛出的异常,针对受检异常相对多些
public static void test2 () throws ArithmeticException {
// int a = 10 / 0;
// System.out.println(a);
String str = null;
System.out.println(str.length());
}
// 在方法中通过throw 抛出异常 ,针对自定义异常,针对需要改变运行流程的情况,使用相对多些
public static void test3() {
try {
int a = 10 / 0;
} catch(ArithmeticException e) {
throw e;
}
}
}
继承Exception或者RuntimeException
一般结合throw一起使用,通过自定义异常,可以实现终止业务逻辑的功能
package com.qfedu.customerex;
// 如果继承Exception类,在其他地方创建并抛出异常类对象,默认会报错(当成受检异常进行处理)
// 个人建议,继承RuntimeException
public class LoginException extends RuntimeException{
// 针对异常信息的编码值
private int code;
// 异常信息
private String msg;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public LoginException(int code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
}
package com.qfedu.customerex;
public class App2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
login(null, "1235");
System.out.println("合法用户");
} catch (LoginException e) {
// System.out.println(e.getMsg());
System.out.println(e.getMessage());
}
}
// 借助抛异常的方式,终止程序的后续逻辑
public static void login(String name, String password) {
if(name == null || name.isEmpty()) {
// 创建了一个自定义异常的对象,然后通过throw抛出
throw new LoginException(101, "请输入用户名");
}
if(password == null || password.isEmpty()) {
throw new LoginException(102, "请输入密码");
}
if(!(name.equals("admin") && password.equals("123"))) {
throw new LoginException(103, "用户名或者密码错误");
}
}
}