2012-09-20 16 views
60

Dlaczego Eclipse daje mi ocieplenie "wyciek zasobów:" w "nigdy nie jest zamknięty" w poniższym kodzie?wyciek zasobów: "w" nigdy nie jest zamknięty

public void readShapeData() { 
     Scanner in = new Scanner(System.in); 
     System.out.println("Enter the width of the Rectangle: "); 
     width = in.nextDouble(); 
     System.out.println("Enter the height of the Rectangle: "); 
     height = in.nextDouble(); 

Odpowiedz

43

Ponieważ nie zamknąć skaner

in.close(); 
+28

To będzie zamknąć 'Scanner' i ciszy ostrzeżenie, ale będzie również blisko' System.in' która zazwyczaj nie jest pożądane. –

+0

@StuartCook +1. Coś, na co warto zwrócić uwagę. – informatik01

+3

Dlaczego musimy zamknąć skaner? Co oznacza "wyciek zasobów"? –

3

Należy close Scanner kiedy jesteś z nim zrobić:

in.close(); 
2

Generalnie instancje klas, które zajmują się Wejścia/wyjścia powinny być zamknięte po ich zakończeniu. Więc na końcu twojego kodu możesz dodać in.close().

6

Informuje o konieczności zamknięcia skanera, który został utworzony na System.in z Scanner.close(). Zwykle każdy czytnik powinien być zamknięty.

Pamiętaj, że zamknięcie System.in uniemożliwi ponowne odczytanie. Możesz także rzucić okiem na klasę Console.

public void readShapeData() { 
    Console console = System.console(); 
    double width = Double.parseDouble(console.readLine("Enter the width of the Rectangle: ")); 
    double height = Double.parseDouble(console.readLine("Enter the height of the Rectangle: ")); 
    ... 
} 
+2

Zauważ, że 'System.console Funkcja() 'nie jest dostępna podczas uruchamiania aplikacji za pośrednictwem środowiska Eclipse, co może być kłopotliwe podczas programowania. –

0

Skaner powinien być zamknięty. Dobrą praktyką jest zamykanie Czytelników, Strumieni ... i tego rodzaju obiektów w celu zwolnienia zasobów i wycieków pamięci; i robiąc to w bloku finally, aby upewnić się, że są zamknięte, nawet jeśli wystąpi wyjątek podczas obsługi tych obiektów.

+0

Ta odpowiedź faktycznie pomaga OP wiedzieć, dlaczego powinien to zamknąć. Oczywiście, może przeczytać dokument i zobaczyć "' scanner.close() '", ale ta odpowiedź naprawdę pomaga mu/jej zrozumieć, co się dzieje. + 1 – HyperNeutrino

36

Jak powiedzieli inni, musisz zadzwonić "zamknij" na zajęciach IO. dodam, że jest to doskonałe miejsce, aby wykorzystać szansę - w końcu zablokować bez połowu, tak:

public void readShapeData() throws IOException { 
    Scanner in = new Scanner(System.in); 
    try { 
     System.out.println("Enter the width of the Rectangle: "); 
     width = in.nextDouble(); 
     System.out.println("Enter the height of the Rectangle: "); 
     height = in.nextDouble(); 
    } finally { 
     in.close(); 
    } 
} 

Gwarantuje to, że skaner jest zawsze zamknięty, gwarantując prawidłowe oczyszczanie zasobów.

równoważnie w Javie 7 lub więcej, można użyć "try-with-zasobów" składnię:

try (Scanner in = new Scanner(System.in)) { 
    ... 
} 
+1

Co oznacza wyciek zasobów i jak wpłynie na mnie? –

+4

@Borat - "wyciek zasobów" oznacza, że ​​niektóre zasoby systemowe (zazwyczaj pamięć) są tracone lub niepotrzebnie tracone. Zwykle będzie to miało wpływ na ciebie, gdy zaczniesz otrzymywać OutOfMemoryErrors wyrzucane podczas normalnej pracy twojego programu. –

+0

Dzięki eric. Wiem, że możesz spowodować błąd, dodając ciąg do siebie w nieskończonej pętli. Nie wiem, jak skaner mógł spowodować ten błąd. –

0
private static Scanner in; 

Naprawiłem go deklarując się jako prywatnej zmiennej statycznej klasy Scanner. Nie wiem, dlaczego to naprawiło, ale to właśnie zalecam zaćmieniem.

+2

wyciszyłeś ostrzeżenie, ale utworzyłeś wyciek zasobów – zacheusz

8

Musisz zadzwonić pod numer in.close() w bloku finally, aby upewnić się, że wystąpił.

Z dokumentacji Eclipse, tutaj jest dlaczego it Flagi ten konkretny problem (nacisk moje):

Klasy implementujące interfejs java.io.Closeable (od JDK 1.5) i java.lang.AutoCloseable (od JDK 1.7) są uważane za reprezentują zasoby zewnętrzne, które powinny zostać zamknięte przy użyciu metody close(), gdy nie są już potrzebne.

Kompilator Eclipse Java może analizować, czy kod przy użyciu takich typów jest zgodny z tymi zasadami.

...

Kompilator flag [naruszenie] "wycieku z zasobów: 'strumień' nigdy nie jest zamknięta".

Pełne wyjaśnienie here.

1

dodanie private static Scanner in; tak naprawdę nie naprawia problemu, tylko usuwa ostrzeżenie. Uczynienie skanera statycznie oznacza, że ​​pozostanie otwarte na zawsze (lub do momentu, gdy klasa zostanie rozładowana, co prawie jest "na zawsze"). Kompilator nie daje już żadnego ostrzeżenia, ponieważ powiedziałeś mu "trzymaj go na zawsze". Ale to nie jest to, co naprawdę chcesz, ponieważ powinieneś zamknąć zasoby, gdy tylko ich już nie potrzebujesz.

HTH, Manfred.

3

Jeśli używasz JDK7 lub 8, możesz użyć try-catch z zasobami. Spowoduje to automatyczne zamknięcie skanera.

try (Scanner scanner = new Scanner(System.in);) 
    { 
    System.out.println("Enter the width of the Rectangle: "); 
    width = scanner.nextDouble(); 
    System.out.println("Enter the height of the Rectangle: "); 
    height = scanner.nextDouble(); 
    } 
catch(Exception ex) 
{ 
    //exception handling...do something (e.g., print the error message) 
    ex.printStackTrace(); 
} 
0
in.close(); 
scannerObject.close(); 

To zamknie Scanner i zamknął ostrzeżenie.

2
Scanner sc = new Scanner(System.in); 

//do stuff with sc 

sc.close();//write at end of code. 
3
// An InputStream which is typically connected to keyboard input of console programs 

Scanner in= new Scanner(System.in); 

powyżej linii wywoła konstruktor klasy skanera z argumentem System.in i powróci odniesienie do nowo skonstruowaną obiektu.

Jest on podłączony do strumienia wejściowego, który jest podłączony do klawiatury, więc teraz w czasie wykonywania można wprowadzić dane użytkownika, aby wykonać wymaganą operację.

//Write piece of code 

Aby usunąć wyciek pamięci -

in.close();//write at end of code. 
Powiązane problemy