为了省6个单词,找了半个多小时的错误

今天在写一个小demo的时候,用到了Scanner,然后我灵机一动。。想着把它放在try-resource-catch里面,因为正好是要用jdbc,所以想利用一下这个resource,于是我就把它放进去了,结果,发生了接下来的一幕。。。

我们来看一下代码

这里就是问题的根源

package jdbc_day1;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;

public class TestLogin {
	static {
		try {
			Class.forName("oracle.jdbc.OracleDriver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public static String login() {
		try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "hr", "hr");
				PreparedStatement ps = conn.prepareStatement("select * from tbl_user where name = ? and pwd = ?");
				Scanner s = new Scanner(System.in);
				) {
			boolean bn;
			//Scanner s = new Scanner(System.in);
			do {
				bn = false;
				System.out.print("请输入帐号");
				String name = s.next();
				System.out.print("请输入密码");
				String pwd = s.next();
				ps.setString(1, name);
				ps.setString(2, pwd);
				ResultSet rs = ps.executeQuery();
				if (rs.next()) {
					System.out.println("登录成功!");
					return name;
				} else {
					System.out.println("登录失败!");
					System.out.println("重新输入-y  退出-n");
					char c = s.next().charAt(0);
					bn = (c == 'y' || c == 'Y') ? true : false;
				}
				rs.close();
			} while (bn);
			//s.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
}

测试类

package jdbc_day1;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

public class TestUpdate {
	static {
		try {
			Class.forName("oracle.jdbc.OracleDriver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "hr", "hr");
				PreparedStatement ps = conn.prepareStatement("update tbl_user set pwd = ? where name = ?");) {
			String name = TestLogin.login();
			Scanner s = new Scanner(System.in);
			if (name != null) {
				System.out.print("请输入新密码:");
				String newPwd = s.next();
				ps.setString(1, newPwd);
				ps.setString(2, name);
				ps.executeUpdate();
				System.out.println("修改成功!");
			}
			s.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

美滋滋的写完了,想着,我真是太机智了,又省了六行代码~~ 舒服

当我运行的时候
在这里插入图片描述
报错了。。。 我找一下错误, 在25行,也就是下面这里
在这里插入图片描述

然后我就懵了,开始怀疑,难道是我昨晚喝多了? s.next()不是这么写的吗。。。然后我换成了s.nextLine();
结果还是如此. 此处省略很多问号。。。 接着,我打开了源码,也就是报错的位置,看下图
在这里插入图片描述

作为三级一遍过的男人,这点英文太简单了
(如果我们在输入的最后,那么NoSuchElement; 如果仍然有输入,那么input失配)
假装我没有用有道词典。但是,这翻译过来也看不懂啥玩意啊…

接着,费劲周折,我把Scanner放到外面,自己手动关闭,结果成功了

public static String login() {
		try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "hr", "hr");
				PreparedStatement ps = conn.prepareStatement("select * from tbl_user where name = ? and pwd = ?");) {
			boolean bn;
			Scanner s = new Scanner(System.in);
			do {
				bn = false;
				System.out.print("请输入帐号");
				String name = s.next();
				System.out.print("请输入密码");
				String pwd = s.next();
				ps.setString(1, name);
				ps.setString(2, pwd);
				ResultSet rs = ps.executeQuery();
				if (rs.next()) {
					System.out.println("登录成功!");
					return name;
				} else {
					System.out.println("登录失败!");
					System.out.println("重新输入-y  退出-n");
					char c = s.next().charAt(0);
					bn = (c == 'y' || c == 'Y') ? true : false;
				}
				rs.close();
			} while (bn);
			s.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

在这里插入图片描述
然后咱们来分析一下原因,这到底是为什么呢?
首先,咱们看一下System.in底层是什么样的
在这里插入图片描述

从这里可以看出System.in底层是封装的一个静态输入流
如果我们将Scanner放入try-resource-catch里面的话,会自动将所有资源关闭,当然包括这个输入流
所有当我们在测试类中调用完login方法之后,这个输入流in已经在login中关闭了,由于是静态的,所以我们在测试类中的in也是关闭的,这个时候,我们用一个关闭的流去接收键盘输入的值,就会报java.util.NoSuchElementException这个错误,但是如果我们手动关闭的话,当登陆成功后,就直接带着返回值返回到调用处了,而s.close();这个语句并没有执行,所以这个流还是开启的.因此就可以正常使用咯~~

从这里可以得到一个小小的经验:在我们使用键盘输入的时候,尽量手动关闭资源,不然稍不注意,可能就会犯我这个错误咯~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值