Scanner类的close()用法的注意点

在写练习的时候碰到了NoSuchElementException异常,编译器显示是Scanner类的使用产生的异常。
在这里插入图片描述
代码如下:

package javaExp5;
import java.util.Vector;
import java.util.Scanner;
public class Exp56 {
	public static void main(String []args)
	{
		Scanner sc=new Scanner(System.in);
		BasketballTeam BallTeam=new BasketballTeam();
		BallTeam.FindMan();
		BallTeam.DeleteMan();
		sc.close();
	}
}
class BasketballTeam{
	Vector<String> NameVec;
	
	BasketballTeam()
	{
		Scanner scan=new Scanner(System.in);
		
		NameVec=new Vector<String>();
		System.out.println("请输入6名球员姓名");
		for(int i=0;i<6;i++)
		{	NameVec.add(scan.next());}
		scan.close();
	}

	void FindMan()
	{
		Scanner sc=new Scanner(System.in);
		System.out.println("请输入查找姓名");
		String name=sc.next();
		if(NameVec.contains(name))
			System.out.println("找到此人!");
		else
			System.out.println("查无此人!");
		sc.close();
	}
	
	void DeleteMan()
	{
		System.out.println("请输入想要删除的姓名");
		Scanner sc=new Scanner(System.in);
		String name=sc.next();
		if(NameVec.contains(name))
		{
			NameVec.removeElementAt(NameVec.indexOf(name));
		}
		else
			System.out.println("无此队员!");
			sc.close();
	}
}

抱着试一试的想法删去了close()方法,发现不报错了。于是将问题锁定到close()方法
再查阅资料得知,Scanner一旦被close就无法再度开启使用了,遂整理了相关结论和解决方法。总结如下。
1.为什么要调用close()?
因为Scanner使用的是io流,会占用很多资源空间,如果一直不释放,会产生很大的浪费。
2.为什么会出现上图的错误?
创建Scanner对象时,括号里的参数是 System.in。而in是一个final类型,它一旦被初始化就不能改变。所以,无论后面创建多少个Scanner类对象,其实都是返回同一个InputStream流。也就是说,每一次赋给新对象的地址是同一个。如果在代码中关闭了Scanner,也就是调用Scanner的close(),就会直接关闭输入流System.in。而System.in一旦关闭,就无法再度开启。所以第二次乃至第三次调用close()的时候,程序就会得不到输入流而直接报错。
3.如何及时使用close()方法
如果一个方法中创建了Scanner对象,却没有关闭,那么在方法结束后,Scanner对象虽然会进入被回收的队列中,但不是立刻回收。而这会给计算机带来一定的负担,为了避免造成大量的内存占据,至少在方法结束前应该调用Scanner的close()方法。
由此我们可以想到,Scanner对象的close应该在用不到的时候尽快释放出去,但一定要在Scanner类的使用全部结束之后。
也就是如下的形式:

void test() {
	Scanner sc=new Scanner(System.in);
	String str=sc.next()
	//代码块
	//其中含有sc.next()/nextInt()等调用sc的方法
	sc.close();
	//代码块
	//其中不含sc的调用
}

4.如何正确使用Scanner类
这个问题是由3衍生出的,因为我在上面出现错误的代码中创建了多个Scanner类对象,如果都不close的话显然也是一个很大的问题,而且close()只需要close一个就足够了吗?我在多个方法中使用Scanner类,怎么确定最后是在哪个方法中close()呢?带着这样的疑问,查阅资料得知:不推荐创建多个Scanner类对象使用一个io流,不安全。那么如何使用呢?

  • 应该在主方法(也就是执行入口)中创建一个Scanner类对象,然后把这个Scanner类对象交给各个方法去调用,在主方法中调用close()关闭
  • 其他所有类中不使用close()方法

调用方法有2种:
1.把Scanner类对象作为参数传递
2.主类名.Scanner类对象名.方法 例:主类名.sc.next()

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值