Java笔记(异常)

一、异常机制

1.碰到过的异常

  1. 下标越界
  2. 空指针异常
  3. 类型转换异常
  4. 栈内存溢出

2.概述

  • 异常是Java中提供的一种识别及响应错误情况的一致性机制。有效地异常处理能使程序更加健壮、易于调试。
  • 异常发生的原因有很多,比如:
    1. 用户输入了非法数据
    2. 要打开的文件不存在
    3. 网络通信时连接中断
    4. JVM内存溢出
    5. 这些异常有的是因为用户错误易引起,有的是程序错误引起的,还有一些是因为物理错误引起的
  1. try…catch… 处理异常的
  2. throws 抛出异常
  3. throw 异常源点
  4. finally 必须执行的语句块

目的:增强程序的鲁棒性,就是健壮性

3.继承体系

在这里插入图片描述

4.Error

系统内部错误,这类错误由系统进行处理,程序本身无需捕获处理。
比如:OOM(内存溢出错误)、VirtualMachineError(虚拟机错误)、StackOverflowError(堆栈溢出错误)等,一般发生这种情况,JVM会选择终止程序。

5.Exception

5.1.概述

Exception是所有异常类的父类。分为非RuntimeException和RuntimeException

  • 非RuntimeException

    n 指程序编译时需要捕获或处理的异常,如IOException、自定义异常等。属于checked异常

  • RuntimeException

    指程序编译时不需要捕获或处理的异常,如:NullPointerException等。属于unchecked异常。一般是由程序员粗心导致的。如空指针异常、数组越界、类型转换异常等

5.2.常用方法

在这里插入图片描述

5.3.Try…catch…

5.3.1.第一种
		int a = 10;
		int b = 0;
		if (b != 0) {
			// 这里就会出现一个错误,除数不能为零
			// java.lang.ArithmeticException: / by zero
			System.out.println(a / b);
			
		} else {
			System.out.println("除数不能为0");
		}

		try {
			// 如果a/b 有错,那么就将错误抛出,直接去执行catch,不再执行try中剩余代码
			System.out.println(a / b);
			System.out.println(5);
			System.out.println(6);
			//如果try中代码顺利执行完,那么将不再执行catch
		} catch (ArithmeticException e) {
			// e.getMessage()获取错误信息,一般给用户看
			System.out.println(e.getMessage());
			// 打印错误详细栈帧,一般给程序员看,用于改错
			e.printStackTrace();
		}
5.3.2.第二种
		try {
			System.out.println(a / b);// 除数不能为0
			String string = null; // 空指针
			string.toString();
			// 注意:多个catch只会有一个执行,因为try中只要发现一个错误就会执行catch
			// 多个catch 传入的异常类型必须是 从子到父 的,也就是最先判断是否属于前面的那个异常,与多分支类似
		} catch (ArithmeticException e) {
			System.out.println("除数不能为零");
		} catch (NullPointerException e) {
			System.out.println("空指针异常");
		} catch (Exception e) {
			System.out.println("其他异常");
		}
5.3.3.第三种
		try {
			System.out.println(a / b);// 除数不能为0
			String string = null; // 空指针
			string.toString();
			// 从java1.7开始,开始支持 异常类型 | 异常类型 | ..... 变量
			// 多个异常不能有继承关系,如果有则直接写父类即可
		} catch (ArithmeticException | NullPointerException e) {
			// TODO: handle exception
		} catch (Exception e) {
			// TODO: handle exception
		}
5.3.4.第四种

java1.7之后有两个改进:

  1. 多个异常可以在一个catch中使用 | 隔开,不能有继承关系
  2. 自动关闭资源

​ try(打开资源){

​ 高风险代码

​ }catch(异常类型 变量){

​ 异常处理

​ }

		FileInputStream files2=null;
		try(FileInputStream files1 = new FileInputStream("E://a.txt");) {
			files2=files1;
			System.out.println("txt:"+files1.read());
		} catch (IOException e) {
			e.printStackTrace();
		} 
		try {
			//java.io.IOException: Stream Closed
			System.out.println("txt:"+files2.read());
		} catch (IOException e) {
			e.printStackTrace();
		}

5.4.Throws

  • throws:抛出异常,并不会处理掉异常,如果最终没有出现try,依然会终止生命周期
  • 是一种提醒机制,告诉大家,这里可能有问题,但是没有解决,多注意
public static void main(String[] args)throws NullPointerException,
			IOException, ArithmeticException, Exception {
try {
			m1();
		} catch (Exception e) {
			e.printStackTrace();
		}
}
// 调用者抛出的异常要么和被调用的方法一样,要么比被调用的抛出的异常更大
	public static void m1() throws Exception {
		m2();
	}

	public static void m2() throws RuntimeException {
		m3();
	}

	public static void m3() throws ArithmeticException {

	}

5.5.Finally

  • 必须执行的语句块,除了System.exit()关闭 JVM 虚拟机之外,finally 一定会执行
  • 所以一般用于做一些关闭资源操作
  • finally 不能单独使用,需要和 try 或者 try…catch… 一起使用
		// 作用域提高指的是声明提高,而不是赋值
		FileInputStream files = null;
		try {
			// 打开对应文件,可能会找不到(如果不存在的话)
			files = new FileInputStream("E://a.txt");
			// 读取文件内容
			System.out.println("txt:"+files.read());
		} catch (IOException e) {//IOException : 输入输出异常
			// 当进行文件读写、网络通信、数据库操作等输入输出操作时,如果发生了IO错误或出现了不可预料的情况,就会抛出IOException异常
			e.printStackTrace();
		} finally {
			// 关闭资源
			if (files != null) {
				try {
					files.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

5.6.不能有更宽泛的异常

class A{
	public void m1() throws IOException{
		
	}
}
//子类要么不抛出异常,要么抛出小于等于父类的异常,绝对不可以比父类异常还要大(就是不能抛出父类异常的父类)
class B extends A{//这里就不能抛出 Exception
	public void m1(){}
}

5.7.final、finally、finalize有什么区别

  • ,final 是修饰符,修饰类不能继承,成员方法不能覆写,变量是常量没有默认值,不能二次赋值
  • finalize 垃圾自动回收时会自动调用该对象的 finalize 方法,一般用于关闭资源等操作,垃圾是没有任何引用指向这个对象时,这个对象就是垃圾,等待被系统回收
  • finally 不许执行的语句块,不能单独出现,必须和 try 或 try…catch… 一起使用

6.自定义异常类

6.1.语法

  • 继承一个已有的异常类,如果是运行时异常则继承 RuntimeException ,否则一般直接继承Exception即可
  • 构造方法,一般需要一个无参构造和一个有参构造用于传入错误信息
public class NameLengthException extends Exception{
	public NameLengthException(){
		
	}
	public NameLengthException(String msg){
		super(msg);
	}
}
public class UserService {
	public static void register(String name) throws NameLengthException{
		if (name.length()<6) {
			//个人理解
			// throw 应该和 return 有异曲同工之妙,就是功能大概差不多
			//只不过 throw 是抛出, return 是返回 ,但是都会终止方法执行
			//后面的 new NameLengthException() 就像新创建的对象 ( 自定义异常的新对象 )
			//里面的内容 ( 这里指"用户名不能小于六位!" ) 就是错误信息,给用户看的
			// 更准确的说法 : throw 会创建一个异常对象,称为异常源
			throw new NameLengthException("用户名不能小于六位!");
		}
	}
}

public class Client {
	public static void main(String[] args) {
		Scanner scanner =new Scanner(System.in);
		System.out.println("请输入用户名");
		String name=scanner.next();
		try {
			UserService.register(name);
			System.out.println("注册成功!");
		} catch (NameLengthException e) {
			//e.printStackTrace();
			System.out.println(e.getMessage());
		}
	}
}

这样就可以实现一个简单的用户名鉴定了 ( 未分层 )

6.2.需求

完成用户登录 ( 分层 )

  1. 如果用户名不是 admin 则提示用户名未注册
  2. 如果密码不是 root 则提示密码错误

6.3.实体类

实体类 封装数据

public class User {
	private String username;
	private String password;
	private String inckname;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getInckname() {
		return inckname;
	}

	public void setInckname(String inckname) {
		this.inckname = inckname;
	}

	public User(String username, String password, String inckname) {
		super();
		this.username = username;
		this.password = password;
		this.inckname = inckname;
	}

	public User() {
		super();
	}

	@Override
	public String toString() {
		return "User [username=" + username + ", password=" + password
				+ ", inckname=" + inckname + "]";
	}

}

6.4.异常类

异常类做 提醒机制

public class UserException extends Exception {
	public UserException() {

	}

	public UserException(String msg) {
		super(msg);
	}
}

6.5.Controller

Controller 是有 main 方法的地方,做前后端交互

public class UserController {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		UserService userService=new UserService();
		System.out.println("请输入用户名:");
		String username=scanner.next();
		System.out.println("请输入密码:");
		String password=scanner.next();
		try {
			User name=userService.login(username, password);
			System.out.println("欢迎登录!"+name.getUsername());
		} catch (UserException e) {
			System.out.println(e.getMessage());
		}
	}
}

6.6.Dao

Dao层负责数据库相关的操作

public class UserDao {

	private User[] users = { new User("admin", "root", "管理员"),
			new User("test", "1111", "测试用户") };
	//模块化分层使代码复用性增强
	public User loadByUsername(String username) {
		for (int i = 0; i < users.length; i++) {
			if (users[i].getUsername().equals(username)) {
				return users[i];
			}
		}
		return null;
	}
}

6.7.Service

Service做业务逻辑处理

public class UserService {
	private UserDao userDao=new UserDao();
	public User login(String username, String password) throws UserException {
		//接受用户传入的数据
		//根据用户名去数据库传输局,如果有就比较密码,,没有则提示用户名不存在
		User oldUser=userDao.loadByUsername(username);
		//比较密码
		if (oldUser==null) {
            //异常机制的用法,自己的代码用法,否则用try...catch...
			throw new UserException("用户名不存在");
		}
		if (oldUser.getPassword().equals(password)) {
			return oldUser;
		}else {
			throw new UserException("密码错误!");
		}
	}
}
  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值