Quoth the Javadoc :
Strumienie mają metodę BaseStream.close () i implementują funkcję AutoCloseable, ale prawie wszystkie instancje strumienia nie muszą być tak naprawdę zamykane po użyciu. Zasadniczo tylko strumienie, których źródłem jest kanał IO (takie jak te zwracane przez Files.lines (Path, Charset)) będą wymagać zamknięcia. Większość strumieni jest wspierana przez kolekcje, tablice lub funkcje generujące, które nie wymagają specjalnego zarządzania zasobami. (Jeśli strumień wymaga zamknięcia, można go zadeklarować jako zasób w instrukcji try-with-resources).
„Prawie wszystkie” i „ogólnie” są niejasne - jeśli piszesz bibliotekę i oddzielasz źródło swojego strumienia od użytkowników tego strumienia, zawsze musisz zadać sobie pytanie - „powinienem zamknąć to?" Strumienie wspierane przez IO muszą zostać zamknięte, ponieważ operacje terminali nie wywołują close
, dlatego zawsze muszę pamiętać / dokumentować, skąd pochodzi mój strumień, lub zawsze muszę to robić close
.
Chyba nuklearną opcją byłoby nie zwracanie strumieni z metod lub akceptowanie parametrów strumienia, co jest sentymentem, który został powtórzony przez niektóre osoby z zespołu JDK. Uważam, że jest to zbyt ograniczające, biorąc pod uwagę praktyczną przydatność strumieni.
Jakie są najlepsze praktyki dotyczące zamykania strumieni? Szukałem w Internecie odpowiedzi na to pytanie od niektórych osób z JDK, które zwykle są aktywne w podobnych pytaniach społeczności, ale nie znalazłem nic istotnego.
Odpowiedzi:
Jak już powiedziałeś, w Javie musisz dokładnie wiedzieć, kto jest odpowiedzialny za zwolnienie którego zasobu, abyś mógł wprowadzić odpowiednie konstrukcje try-catch, try-with-resources lub jakoś delegować to zadanie.
Jedyną rzeczą, którą możesz wyczyścić za pomocą GC, jest 100% czysta pamięć.
Jeśli nie może być jakieś inne zasoby mieszane w, jedyną rzeczą, jaką możesz zrobić, to po prostu rozsądnie grać to bezpieczne.
źródło
close
jest jedyną bezpieczną alternatywą? Myślę, że pytanie brzmi: jak sprawić, by kod nie wyglądał zbyt brzydko za każdym razem, gdy Stream byłby przydatny w użyciu.Jeśli chodzi o „najlepsze praktyki”, myślę, że dobrym pomysłem jest stosowanie konwencji nazewnictwa w przypadku metod zwracających „strumienie zasobów”.
Jeśli trzeba
close()
edytować strumień, należy wywołać metodę fabrycznąopen()
lubopenStream()
. Wywołaj metody, które konstruują efemeryczne strumieniestream()
, zgodnie z konwencją ustanowioną przez SDK. Zawsze używaj metody javadoc, aby ostrzec klienta, że musiclose()
to zrobić.Chciałbym, aby autorzy SDK nie zdecydowali się na umieszczenie
AutoCloseable
w klasie strumienia podstawowego. WyraźnyResourceStream
podtyp, który w trywialny sposób wdrażaAutoCloseable
, uczyniłby różne umowy oczywistymi. Wówczas nie można było zamknąćStream
niepotrzebnego i można było wykryć potencjalnie niewłaściwe zarządzanieResourceStream
narzędziami do analizy statycznej.W zależności od potrzeb twojej bazy kodu (i twojej zdolności do egzekwowania konwencji podczas przeglądania kodu) możesz sam stworzyć ściśle wymaganą podklasę strumienia. Lub jeśli chcesz zbudować własne narzędzia analizy statycznej, adnotację metody, która bezpośrednio oznacza zarządzane zasoby.
źródło