java的Scanner類的close()方法--一個神奇的方法
在學習Java學習中Scanner類是比較常用的類。殊不知,其中隱藏着大秘密。如不小心使用地它的close(),方法,便會釀成大錯。如: java.util.NoSuchElementException。在向程序輸入時一般這樣,
Scanner sc = new Scanner(System.in);
聲明一個Scanner對象。new Scanner(xxxx)-->括號里傳入的時IuputStream類的對象。下面是用到的Scanner類的構造方法
這就說明 system.in 得到的時IuputStream類的對象。事實也是如此,在System類里,in 是InputStream類型,並且是final,即常量,被初始化后就不能被改變了。
Scanner sc = new Scanner(System.in);
搞明白了Scanner對象創建原理那就上代碼吧
1 Scanner sc = new Scanner(System.in);
2 String next = sc.next();
3 //sc.close();
4 Scanner aa = new Scanner(System.in);
5 String next1 = aa.next();
運行如上代碼輸入字符,回車,誒!好像沒問題。但是你可能忘了一件重要的事情,IuputStream是一個流,在不用的時候需要關閉,如不關閉流,它是很消耗資源的。
可能在學習的時候還沒有甚麽大不了,當需要真正開發一個程序時,為了更好的優化程序,這就是很有必要的。於是放開了第3行的代碼,讓它關閉。再次愉快的輸入,回車,驚喜發生了。
解決方式:在Scanner使用的最后才關閉流,這樣既不會報錯,也不會造成資源的浪費。當然最好時開啟流和關閉流在同一個方法里,這樣增大了代碼的可讀性,也提高了代碼的不易錯性。
而且不多次new Scanner對象,虛擬機堆中的垃圾也會減少。如是想在其他方法里使用Scanner對象最好將該scanner對象當參數傳進。
代碼場景:可能一般不會連着使用多個Scanner對象,但是有可能同一個方法里調用再多個方法而這些方法可能會用到Scanner對象。
接下來重頭戲登場。
報錯的原因:上面創建Scanner對象時,括號里的參數是 System.in 而in於是一個final類型,它一旦被初始化就不能改變。所以,不過你后面創建多少個Scanner類對象,其實都是返回同一個InputStream流。也就是說,每一次賦給新對象的地址是同一個。
一旦關閉流時,后面的對象所用的流就是關閉狀態。驚喜就會產生!若是不注意可能寫了很多代碼后才報錯,這樣就很難找到真正的錯誤點。當然也可以通過反編譯查看調用情況。
close()用時須謹慎!