Java 异常
:是Java提供的识别错误的响应机制,可以使程序更加健壮易于调试
异常是错误的另一种说法
Java有一种专门模仿所有异常的类,Throwable是异常类的祖类,所有异常类都是他的子类
如果程序出现了异常,会终止程序生命周期执行,需要进行处理
异常处理形式
try...catch...:解决异常,一般用在客户端(调用处)
throws:抛异常,一般用在类库端(服务端,被调用的地方)
throw:异常源,制作异常,创建异常对象
平时常见的异常
1.下标越界(数组)
2.空指针异常(数组,面向对象)
3.栈内存移出(递归)
4.类型转换异常(面向对象)
5.数字格式化异常(常用API)
异常类继承体系
Error
- 概念
系统内部错误,这类错误由系统进行处理,程序本身无需捕获处理比如:OOM(内存溢出错误)、VirtualMachineError(虚拟机错误)、StackOverflowError(堆栈溢出错误)等,一般发生这种情况,jvm会终止程序
例如:
//堆栈溢出错误
public class TestError{
public static void recusionMethod(){
recusionMethod();//无限递归下去
}
}
Exception
Exception是所有异常类的父类。分为非RuntimeException和RuntimeException 。
非RuntimeException
指程序编译时需要捕获或处理的异常,如IOException、自定义异常等。属于checked异常。
RuntimeException
指程序编译时不需要捕获或处理的异常,如:NullPointerException等。属于unchecked异常。一般是由程序员粗心导致的。如空指针异常、数组越界、类型转换异常等。
常用方法
Try...catch...
第一种语法:
try{
高风险代码
}catch(){
}
=================================
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Exception_02 {
public static void main(String[]args){
try{
//高风险可能出错的代码
//可能找不到这个文件,需要处理
FileInputStream fis = new FileInputStream("D://Aa.txt");
System.out.println("xxx");
}catch(FileNotFoundException e){
//打印追踪栈帧,方便排错
e.printStackTrace();
//获取错误信息,方便查看
String msg = e.getMessage();
System.out.println(msg);
//出错后的处理措施
System.out.println("文件不存在");
}
//代码可以正常执行
System.out.println("====================================");
}
}
====================================
第二种语法
Try{
高风险代码
}catch(异常类型 变量){
} catch(异常类型 变量){
}
============================
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Exception_03 {
public static void main(String[]args){
try{
new FileInputStream("D:/a.t2xt");
String s = null;
s.equals("");
//可以写多个catch捕捉多个异常,进行不同的处理
//多个异常之间不能有继承关系,否则就必须是从子类到父类,否则会因为多态的原因把异常对象获取
}catch(FileNotFoundException e){
System.out.println("找不到文件");
}catch(NullPointerException e){
System.out.println("空指针");
}
}
}
========================
第三种
Java 1.7新改进
自动关闭资源
Try(开启资源){
高风险代码
}catch(异常类型 变量){
}
import java.io.FileInputStream;
import java.io.IOException;
public class Exception_05 {
public static void main(String[]args){
FileInputStream fis1 = null;
try( FileInputStream fis = new FileInputStream("D://a.txt");
//资源2
//资源3
){
//操作,自动关闭,不用finally
fis1 = fis;
System.out.println(fis.read());
}catch(Exception e){
e.printStackTrace();
}try{
//Stream Closed
System.out.println(fis1.read());
}catch(IOException e){
e.printStackTrace();
}
}
}
Throws
Throws 把异常抛出,是一种提醒,跟调用处说明,这里可能有异常,可以抛出多个异常,之间用逗号隔开
========
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Exception_06 {
public static void main (String[]args){
try{
m1();
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(NullPointerException e){
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}System.out.println("=========================");
}
public static void m1()throws FileNotFoundException,Exception,
NullPointerException{
m2();
}
public static void m2()throws FileNotFoundException{
new FileInputStream("");
}
}
Finally
Finally:是必须执行的语句,只有一种情况不执行,System.exit(0);
1.finally 不能单独使用2.必须和try一起或者try…catch一起使用
public class Exception_07 {
public static void main (String[]args){
try{
String s = null;
s.equals("");
//空指针异常,终止程序生命周期
}finally{//必须执行
System.out.println("=============");
}
//因为catch,所以没有办法捕捉异常,依旧会终止生命周期,所以下面代码不会执行
System.out.println("-----------------------------");
}
}
不能有更宽泛的异常
import java.io.FileNotFoundException;
public class Exception_08 {
}
class a {
public void m1() throws FileNotFoundException {
}
}
class b extends a{
// 抛出的异常类,要么和父类抛出的异常类一样
// 要么就是父类抛出的异常类的子类
// 要么 就不抛出异常
public void m1() throws FileNotFoundException {
}
}
自定义异常
自定义异常类
1.继承一个已有的异常类
一般我们继承Exception即可,如果是运行时异常,则继续RuntimeException
2.公共的无参构造
3.有参构造,传入String是错误信息
public class test extends Exception{
public test(){
}
public test(String msg){
super(msg);
}
}
应用场景
需求 :
完成用户登陆
1 用户拥有 username,password,nickname三个属性
2 业务逻辑类,提供登陆方法,校验是否登陆成功
准备用户数组,保存用户信息(相当于是数据库)
3 入参是 用户名和密码 , 出参也是用户对象,登陆成功之后,返回用户的所有信息
4 客户端类,接收用户输入,进行登陆校验
// TODO 注册
try {
userService.add(new User(username, password, nickname));
System.out.println("注册成功");
// TODO 跳转页面 或者数据传递到页面
} catch (UserException e) {
System.err.println(e.getMessage());
}
} else if (value == 2) {
System.out.println("请输入 : 用户名");
String username = scanner.next();
System.out.println("请输入 : 密码");
String password = scanner.next();
// TODO 登陆
try {
User loginUser = userService.login(username, password);
System.out.println("登陆成功,欢迎 " + loginUser.getNickname()
+ " 回来");
System.out.println(loginUser);
} catch (UserException e) {
System.err.println(e.getMessage());
// TODO 错误信息传递给页面
}
}
}
public class UserException extends Exception {
public UserException() {
}
public UserException(String msg) {
super(msg);
}
}
public class UserService {
private UserDao userDao = new UserDao();
/**
* 用户注册
*
* @param user
* @throws UserException
*/
public void add(User user) throws UserException {
// 1 判断用户名是否重复(根据用户名查询,能找到就是重复)
User oldUser = userDao.loadByUserName(user.getUsername());
// 2 重复就抛异常 : 用户名已重复
if (oldUser != null) {
// 创建一个异常对象并抛出,并且throw有终止运行的作用
throw new UserException("用户名已存在");
}
// 3 不重复 就添加
userDao.add(user);
}
/**
* 登陆
*
* @param username
* @param password
* @return
* @throws UserException
*/
public User login(String username, String password) throws UserException {
// 1 根据用户名查询用户
User user = userDao.loadByUserName(username);
// 2 如果用户不存在,说明用户名不正确
if (user == null) {
throw new UserException("用户名不存在");
}
// 3 如果查询到了用户,就比较密码
// 4 密码不对,.说明密码不对
if (!user.getPassword().equals(password)) {
throw new UserException("密码不正确");
}
// 5 密码正确,登陆成功
return user;
}
}