异常机制
到现在遇到过的异常有:
1 空指针异常
2 下标越界异常
3 类型转换异常
4 栈内存溢出
1.概述
异常是Java中提供的一种识别及响应错误情况的一致性机制。有效地异常处理能使程序更加健壮、易于调试。
异常发生的原因有很多,比如:
- 用户输入了非法数据
- 要打开的文件不存在
- 网络通信时连接中断
- JVM内存溢出
- 这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。
异常 其实就是错误的一种说法,在java中 有一个专门模拟所有异常和错误的类 Throwable,是所有异常类的父类
2.继承体系
3.Error
系统内部错误,这类错误由系统进行处理,程序本身无需捕获处理。
比如:OOM(内存溢出错误)、VirtualMachineError(虚拟机错误)、StackOverflowError(堆栈溢出错误)等,一般发生这种情况,JVM会选择终止程序。
4.Exception
-
4.1 概述:
Exception是所有异常类的父类。分为非RuntimeException和RuntimeException 。
非RuntimeException
指程序编译时需要捕获或处理的异常,如IOException、自定义异常等。属于checked异常。
RuntimeException
指程序编译时不需要捕获或处理的异常,如:NullPointerException等。属于unchecked异常。一般是由程序员粗心导致的。如空指针异常、数组越界、类型转换异常等。 -
4.2 常用方法:
返回关于发生的异常的详细信息,这个消息在Throwable类的构造函数中初始化了
public String getMessage();
打印错误栈帧和信息,一般用于程序员排错
public void printStackTrace();
例如
public class Exception_02 {
public static void main(String[] args) {
try {
// 加载对应的文件
FileInputStream fis = new FileInputStream("1.txt");
System.out.println("======");
} catch (Exception e) {
// 打印错误栈帧和信息,一般用于程序员排错
e.printStackTrace();
// 获取错误信息,一般用于反馈给客户端
String msg = e.getMessage();
System.out.println("e.getMessage(): " + msg);
}
// 不再终止生命周期
System.out.println(11111111);
}
}
-
4.3 try…catch…:
处理异常,一般用于客户端
try { -
高风险代码;(只要出错,就执行catch,try中剩余代码不再执行,如果没出错,try就可以顺利执行完成,并且catch不再执行)
}catch(异常类型 变量){
-
处理方案;
}
例子同4.2例
同时,也可以多个catch一起使用捕捉不同类型的异常。但是从上往下必须是子类到父类,或者没有继承关系
try{
高风险代码;
}catch(异常类型 变量){
处理措施;
}catch(异常类型 变量){
处理措施;
}catch(异常类型 变量){
处理措施;
}......
还有一种情况是同时捕捉多种异常,中间用 | 隔开,并且不能有继承关系,如果存在继承关系,直接写父类
try{
}catch(异常类型 1 | 异常类型 2 | 异常类型 3 ...){
}
- 4.4 throws:
throws 抛出异常,该方式并不会处理理解,一种提醒机制,告诉调用人员这里可能会有错误,如果知道如何解决,则使用try解决问题,否则就要通过throws抛出问题(throws可以同时抛出多个异常,用逗号隔开)只要你的下家提醒了你,要么你解决,要么抛给上家
public class Exception_03 {
public static void main(String[] args) {
try {
m1();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("===");
}
public static void m1() throws FileNotFoundException {
m2();
}
public static void m2() throws FileNotFoundException {
m3();
}
public static void m3() throws FileNotFoundException {
new FileInputStream("123");
}
}
- 4.6 finally:
必须执行的语句块,不能单独使用,必须和try或者 try.catch一起使用,只有一种不执行的情况,那就是 System.exit(0);
public class Exception_07 {
public static void main(String[] args) {
int result = m1();
System.out.println(result);
}
public static int m1() {
int i = 10;
try {
return i++;
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(i + "-------");
return i;
}
}
}
--------------------------------------------------------------------------------------------------------------------------
java7新特征,自动关闭资源
try(开启资源语句;){
高风险代码;
}catch(异常类型 变量){
处理方案;
}
public class Exception_09 {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("123")) {
// 操作
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 4.6 不能有更宽泛的异常:
方法覆写时不能比原方法有更宽泛的异常,子类方法抛出的异常,不能大于父类异常,也就是小于等于父类异常均可,要么和父类抛出的异常一致,要么是父类抛出的异常类的子类,或者直接不抛出异常
5.自定义异常类
-
5.1 需求:
完成用户登陆功能
传入用户信息,校验用户名和密码是否正确,如果正确则返回该用户所有信息,反之则提示错误信息
-
5.2 实体类:
public class User {
// 账号
private String username;
// 密码
private String passwd;
// 昵称
private String nickname;
public User() {
super();
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "用户名: " + this.username + "密码: " + this.passwd + "昵称: "
+ this.nickname;
}
// 登录验证时候使用
public User(String username, String passwd) {
super();
this.username = username;
this.passwd = passwd;
}
// 注册的时候使用
public User(String username, String passwd, String nickname) {
super();
this.username = username;
this.passwd = passwd;
this.nickname = nickname;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
- 5.3 异常类:
//自定义异常类
public class UserException extends Exception {
public UserException() {
}
public UserException(String msg) {
super(msg);
}
}
- 5.4 controller:
public class UserController {
private static UserService userService = new UserService();
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请选择 1.注册 2.登录");
int tag = scanner.nextInt();
if (tag == 1) {
System.out.println("请输入用户名");
String username = scanner.next();
System.out.println("请输入昵称");
String nickname = scanner.next();
System.out.println("请输入密码");
String passwd1 = scanner.next();
while (true) {
System.out.println("请再次输入密码");
String passwd2 = scanner.next();
if (passwd2.equals(passwd1)) {
break;
}
System.out.print("密码不一致,");
}
User userInput = new User(username, passwd1, nickname);
try {
User user = userService.userAdd(userInput);
System.out.println(user.getUsername() + ",您好");
} catch (UserException e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
}
} else {
System.out.println("请输入账号");
String username = scanner.next();
System.out.println("请输入密码");
String passwd = scanner.next();
User userInput = new User(username, passwd);
try {
User loginUser = userService.userLogin(userInput);
System.out.println(loginUser);
} catch (UserException e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
}
}
}
}
}
- 5.5 data:
//模拟数据库
import Homework.Practice.Pojo.User;
public class UserDatabase {
private static User[] users = null;
static {
users = new User[2];
users[0] = new User("admin", "root", "管理员");
users[1] = new User("test", "123456", "普通账户");
}
// 添加
public static void add(User u) {
User[] newUsers = new User[users.length];
System.arraycopy(users, 0, newUsers, 0, users.length);
newUsers[newUsers.length - 1] = u;
users = newUsers;
}
public static User[] getUsers() {
return users;
}
public static void setUsers(User[] users) {
UserDatabase.users = users;
}
}
- 5.6 dao:
public class UserDao {
// 检查用户是否存在
public User checkUsername(String username) {
User[] user = UserDatabase.getUsers();
for (int i = 0; i < user.length; i++) {
if (username.equals(user[i].getUsername()))
return user[i];
}
return null;
}
// 注册
public void add(User user) {
UserDatabase.add(user);
}
}
- 5.7 service:
public class UserService {
private UserDao usedao = new UserDao();
// 登录
public User userLogin(User u) throws UserException {
User user = new User();
user = usedao.checkUsername(u.getUsername());
if (user == null)
throw new UserException("账号不存在");
if (u.getPasswd() .equals(user.getPasswd()))
return user;
else
throw new UserException("密码不对");
}
// 注册
public User userAdd(User u) throws UserException {
User user = new User();
user = usedao.checkUsername(u.getUsername());
if (user != null) {
throw new UserException("账号已存在");
} else {
usedao.add(u);
return u;
}
}
}