2014-05-13 102 views
8

我正在學習Java並在某些項目上工作以獲得樂趣。我在已經運行的一個問題是,當我使用Scanner對象的Eclipse警告我說:Java - 關閉掃描程序和資源泄漏

Resource Leak: 'scan' is never closed.

所以,我在我的代碼的末尾添加一個scan.close();而這需要警告的照顧。

問題出現了,因爲我在同一個包中使用了掃描器對象的其他類,並且Eclipse告訴我要分別關閉這些類中的掃描器。但是,當我這樣做時,它似乎關閉了所有掃描器對象,並且在運行時遇到錯誤。

這裏是什麼原因導致的錯誤示例:

import java.util.Scanner; 
public class test2 { 
    public static void main(String [] args) { 
     Scanner scan = new Scanner(System.in); 
     int test = 0; 
     do {  
      //Do stuff 
      test = scan.nextInt(); 
      System.out.println(test); 

      scanTest scanTest = new scanTest(); 
      scanTest.test(); 
     } while (test != 0); 

     scan.close();  
    } 
} 

import java.util.Scanner; 
public class scanTest { 
    public void test() { 
     Scanner scanner = new Scanner(System.in); 
     int blah = scanner.nextInt(); 
     System.out.println(blah); 
     scanner.close(); 
    } 
} 

掃描儀關閉後在scanTest類,並進入了test2 do循環再次在該行test = scan.nextInt();

我發生錯誤嘗試將掃描器對象的創建移動到do循環中,以便每次都創建一個新對象,但錯誤仍然存​​在。

不知道爲什麼會發生這種情況,或者我可以確保所有I/O對象都被關閉而不會出現問題。

我遇到過的一篇文章提到,當System.in已關閉時,我無法重新打開。如果是這種情況,我只需要確保在程序的最後關閉System.in的掃描器對象,並在其他類中禁止所有其他掃描器警告。或者仍然會讓所有這些掃描儀對象打開(壞)?

+0

這裏有一個很好的討論這個問題:http://stackoverflow.com/questions/12519335/resource-leak-in-is-never-closed – azurefrog

+0

我相信的訣竅是,你只允許一個掃描儀對象綁定到System.in對象中。因此,您需要構建代碼以利用這一個Scanner對象。 –

回答

3

首先,這沒有內存泄漏。

其次,關閉流封裝器時,默認實現是關閉它封裝的流。這意味着你第一次關閉你的掃描儀(就像它被寫入),是的,你關閉了System.in。

一般來說,如果想要再次從System.in中讀取數據,則希望避免關閉System.in。最好的辦法取決於你的程序。

可以將信息從System.in複製到某種緩衝區中,然後掃描緩衝區。有人可能不關閉掃描儀,在其他位置重新使用它。有人甚至可能會取消Scanner的垃圾收集功能,並在System.in上創建多個新掃描儀。

這些解決方案並不完全等同,有些被認爲比別人好得多;但是,這一切都取決於調用程序。嘗試一些,如果遇到問題,請打開一個新的StackOverflow問題,其中顯示代碼的相關部分,問題描述,示例輸入和錯誤輸出(以及所需的輸出)。

祝你好運。

+0

這也不是資源泄漏。事實上,它不會泄漏任何東西。這只是對預期行爲的誤解。 –

+0

謝謝您的評論。如果我沒有關閉特定類中的Scanner(System.in),但是確保在程序結束時關閉了System.in,那麼可以嗎?那麼我在其他類中使用的所有其他Scanner(System.in)對象是否也會被關閉? – SuperCow

3

是的,關閉掃描儀時,您將關閉底層流(在本例中爲System.in)。爲避免這種情況,可以創建一個掃描儀的全局變量,它可以被所有的類使用,或者有一個關閉掃描儀的中心點(在程序退出之前是理想的)

+0

使用全局變量可能會很容易在我的程序中使用,然後我可以在程序退出之前關閉它。但是,我的許多老師都建議,如果不滿意,可以使用全局變量。 – SuperCow

+0

在這種情況下,考慮使用包含掃描器對象的公共靜態類 - 實現相同的功能。 –

0

不要將所有掃描儀都命名爲相同。如果你在一個這樣的事有多個:

import java.util.Random; 
import java.util.Scanner; 

public class DayThree { 

    public static void main(String[] args) { 

     **Scanner textScanner = new Scanner(System.in);** 

     // boolean operands 
      // String(or objects) .equals()  "this".equals("that")  false 
      // primitive data types  ==   'a'=='a' -> true 5==6 false 
      //        !=   'a'!='a' -> false 5!=6 true 
      //        !   !(true) -> false !(false) true 
      //        >   5 > 4  -> true 'a' > 'b' false 
      //        <   5 < 4  -> false 
      //        <=   
      //        >=  
      //  &&  -> and  5 < 6 && 7 > 10 -> false 
         // if either side of and is false the outcome is false 
      //  ||  -> or  5 < 6 || 7 > 10  -> true 
         // if either side of or is true the outcome is true 
     //System.out.println(!(5 < 10) && (7>3) || (true && false || true)); 

     /*  <-- this is a multi line comment 
      System.out.println("What is the most amazing show on tv this week? "); 
      String show = textScanner.nextLine().toLowerCase(); //this is case sensitive 

      show = show.toLowerCase(); // changes the strng to a lowercase version 
      show = show.toUpperCase(); 

      if(show.equalsIgnoreCase("game of thrones")){ // .equalsIgnoreCase(ignores caps/lower) 
       System.out.println("Yes it is!"); 
      } 
      else{ 
       System.out.println("You are wrong."); 
       System.out.println(show + " is clearly inferior to Game of Thrones."); 
      } 

      System.out.println("Who is your favorite character in " + show + "."); 
      String character = textScanner.nextLine().toLowerCase(); 

      if(character.contains("dragon")){ 
       System.out.println("CGI magic is so cool!"); 
      } 
      else if(character.contains("lanister")){ 
       System.out.println("Wrong house."); 
      } 
      else{ 
       System.out.println(character + "is pretty cool I guess..."); 
      } 
     */ 
//  asdf  alternate multi line comment use ctrl +/on highlighted text. 
//      doing this a second time undoes the comment 
//  sdaf 
//  asdf 
//  asdf 
//  asdf 

//  1. ask about favorite something (pet) 
//  2. save that into a string all lowercase 
//  3. have a series of if else (x3) and else statements about the something 

     //NOTE: DO NOT END CONDITIONALS WITH ; example: if(boolean); IS WRONG. 
     **Scanner numScanner = new Scanner(System.in);** // the variable tells you what to use it for 
     Random rand = new Random(); // this makes a new random object 
     System.out.println("Pick a number."); 
     int num = numScanner.nextInt(); 
     int sNum = rand.nextInt(9) + 1; // gives me a random num between 1-10 
             // nextInt(bound)gives you a num from 0-bound 
             //adding one gives you a num from 1 - bound + 1 
     if(num > sNum){ 
      System.out.println("Too high"); 
      System.out.println("The number was " + sNum); 
     } 
     else if(num < sNum){ 
      System.out.println("Too low"); 
      System.out.println("The number was " + sNum); 
     } 
     else{ 
      System.out.println("Wow are you psychic? "); 
     } 
     textScanner.close(); 
     numScanner.close(); 
    }//main method 

} 

*scanner name goes here*.close();爲您掃描儀各一臺。如果它們都具有相同的名稱,則更改與其他掃描儀不同的內容。