如果在代码中关闭了Scanner,也就是调用了Scanner.close()这个方法,那么在接下来的代码中将无法再使用Scanner,即便再次声明了一个新的Scanner对象也是如此。

首先Scanner的close()方法会关闭System.in,也就是Scanner对象在被初始化时所传入的参数。

System.in是一个final常量,所以在整个方法中只会被实例化一次。

这也就导致了在第二次创建Scanner对象的时候并没有一个全新的System.in被传入,而是一个已经被关闭了的System.in。

那么是否能够重新打开System.in呢?

就目前查到的资料中表示System.in在被关闭后并不能重新打开,对于具体原因还不清楚。

所以如果要关闭Scanner的话一定要确保在同一方法下接下来不会再调用Scanner来接受输入。

接下来是为什么要关闭Scanner。

我们之所以要关闭Scanner是因为System.in在被第一次声明时会打开InputStream,而输入流是非常占据内存的,为此我们通常为了节省内存考虑会选择调用Scanner.close()来关闭输入流,从而节省内存。

如果一个方法中创建了Scanner对象,却没有关闭,那么在方法结束后,Scanner对象虽然会进入被回收的队列中,但不是立刻回收。而这会给计算机带来一定的负担,为了避免造成大量的内存占据,至少在方法结束前应该调用Scanner的close()方法。

例如:

public int run(){

Scanner sc = new Scanner(System.in);//创建Scanner对象

int i = sc.nextInt();

//代码块(其中再次调用了sc)

sc.close()//关闭Scanner,也就是关闭输入流

//如果不写sc.close()的话尽管sc同样会在一段时间后被回收,但如果run函数被大量重复调用的话,就会导致一定程度的内存浪费

return i;

}



需要注意的是,如果函数中有多个地方可能会结束方法,那么要在每次结束前确保Scanner对象被close了。

但如果能够保证接下来的部分不会在运用到Scanner,也可以提早进行Scanner的close()方法的调用。

这也就是为什么Scanner的close()不是总被放在最后的原因。

同时Scanner在方法中也占据了一定的内存,会影响到运行,能够及早释放也会更好。

例如:

public int run(){

Scanner sc = new Scanner(System.in);//创建Scanner对象

int i = sc.nextInt();

sc.close()//关闭Scanner

//代码块(其中没有调用sc)

return i;

}



这样可以进一步节省内存,也保证了不用担心后面会出现突然结束方法而没有关闭Scanner的情况。

ps:虽然这样就要注意是否要再次调用Scanner了。