Jestem w trakcie nauki języka Java i nie mogę znaleźć dobrego wyjaśnienia na implements Closeable
temat implements AutoCloseable
interfejsów i.
Kiedy zaimplementowałem interface Closeable
, moje Eclipse IDE utworzyło metodę public void close() throws IOException
.
Mogę zamknąć strumień pw.close();
bez interfejsu. Ale nie mogę zrozumieć, jak mogę zaimplementować close()
metodę za pomocą interfejsu. Jaki jest cel tego interfejsu?
Chciałbym również wiedzieć: jak mogę sprawdzić, czy IOstream
rzeczywiście był zamknięty?
Użyłem podstawowego kodu poniżej
import java.io.*;
public class IOtest implements AutoCloseable {
public static void main(String[] args) throws IOException {
File file = new File("C:\\test.txt");
PrintWriter pw = new PrintWriter(file);
System.out.println("file has been created");
pw.println("file has been created");
}
@Override
public void close() throws IOException {
}
Odpowiedzi:
Wydaje mi się, że nie znasz zbyt dobrze interfejsów. W opublikowanym kodzie nie musisz implementować
AutoCloseable
.Musisz (lub powinieneś) wdrożyć
Closeable
lubAutoCloseable
jeśli masz zamiar zaimplementować własnePrintWriter
, które obsługuje pliki lub inne zasoby, które należy zamknąć.W Twojej realizacji wystarczy zadzwonić
pw.close()
. Powinieneś to zrobić w ostatnim bloku:Powyższy kod jest związany z Javą 6. W Javie 7 można to zrobić bardziej elegancko (zobacz tę odpowiedź ).
źródło
PrintWriter
? ZwłaszczaAutoClosable
przedmioty mogą być używane w wielu innych okolicznościach niż tylkoPrintWriter
...PrintWriter
więc wspomniałem o nim bardziej szczegółowo.AutoCloseable
? Lepiej pokażtry-with-resources
zamiast tego…AutoCloseable
(wprowadzone w Javie 7) umożliwia użycie idiomu try-with-resources :Teraz możesz powiedzieć:
a JVM zadzwoni
close()
automatycznie.Closeable
to starszy interfejs.Z jakiegoś powoduAby zachować zgodność z poprzednimi wersjami, projektanci języków postanowili stworzyć oddzielny. Pozwala to nie tylko na użycie wszystkichCloseable
klas (takich jak rzucanie strumieniIOException
) w próbach z zasobami, ale także pozwala na rzucanie bardziej ogólnych sprawdzonych wyjątków zclose()
.W razie wątpliwości użyj
AutoCloseable
, użytkownicy Twojej klasy będą wdzięczni.źródło
Closeable.close()
rzutyIOException
. Wieleclose()
metod, które mogłyby skorzystać z try-with-resources, rzucają inne sprawdzone wyjątki (np.java.sql.Connection.close()
TakAutoCloseable.close()
rzucaException
. Zmiana istniejącegoCloseable
kontraktu spowodowałaby zerwanie wszystkich istniejących aplikacji / bibliotek opierających się na kontrakcie, któryclose()
tylko generuje,IOException
a nie wszystkie (zaznaczone) wyjątki.Closeable.close()
musi być idempotentny.AutoCloseable.close()
nie jest, chociaż nadal jest to zdecydowanie zalecane.public void close( ) throws Exception
- jeśli możesz, użyj bardziej szczegółowego wyjątku (np. IOException)Closeable
nie gwarantuje idempotencji. To wymaga idempotentność w realizacji użytkownika oclose()
metodzie. AIOException
to, czy jest bardziej szczegółowe / odpowiednie, zależy od przypadku użycia.Closeable
extendsAutoCloseable
i jest specjalnie dedykowany dla strumieni IO: zgłasza IOException zamiast Exception i jest idempotentny, podczas gdy AutoCloseable nie zapewnia tej gwarancji.Wszystko to jest wyjaśnione w javadoc obu interfejsów.
Zaimplementowanie AutoCloseable (lub Closeable) pozwala na użycie klasy jako zasobu konstrukcji try-with-resources wprowadzonej w Javie 7, co umożliwia automatyczne zamykanie takich zasobów na końcu bloku, bez konieczności dodawania końcowego bloku, który zamyka zasób jawnie.
Twoja klasa nie stanowi zamykalnego zasobu i nie ma absolutnie żadnego sensu w implementowaniu tego interfejsu: IOTest nie może zostać zamknięty. Nie powinno być nawet możliwe utworzenie jej wystąpienia, ponieważ nie ma żadnej metody instancji. Pamiętaj, że implementacja interfejsu oznacza, że istnieje plik relacja is-a między klasą a interfejsem. Nie masz tutaj takiego związku.
źródło
Oto mały przykład
Oto wynik:
źródło
this.close()
czy coś w kodzie ?, ponieważ jest wywoływane automatycznie. (Dla pewności)try-with-resources
Komunikat.try-with-resources statement
Jesttry
stwierdzenie, że deklaruje jeden lub więcej zasobów. Aresource
to obiekt, który musi zostać zamknięty po zakończeniu programu.try-with-resources statement
Gwarantuje, że każdy zasób jest zamknięty na końcu instrukcji. Każdy obiekt, który implementujejava.lang.AutoCloseable
, który zawiera wszystkie implementowane obiektyjava.io.Closeable
, może być używany jako zasób.Poniższy przykład odczytuje pierwszy wiersz z pliku. Używa instancji
BufferedReader
do odczytywania danych z pliku.BufferedReader
to zasób, który musi zostać zamknięty po zakończeniu programu z nim:W tym przykładzie zasób zadeklarowany w instrukcji try-with-resources to BufferedReader. Instrukcja deklaracji pojawia się w nawiasach bezpośrednio po słowie kluczowym try. Klasa
BufferedReader
w języku Java SE 7 i nowszych implementuje interfejsjava.lang.AutoCloseable
. PonieważBufferedReader
instancja jest zadeklarowana w instrukcji try-with-resource, zostanie zamknięta niezależnie od tego, czy instrukcja try zakończy się normalnie, czy nagle (w wynikuBufferedReader.readLine
wyrzucenia metodyIOException
).W wersjach starszych niż Java SE 7 można użyć
finally
bloku, aby upewnić się, że zasób zostanie zamknięty, niezależnie od tego, czy instrukcja try zakończy się normalnie, czy nagle. Poniższy przykład używafinally
bloku zamiasttry-with-resources
instrukcji:Zapoznaj się z dokumentacją .
źródło
Niedawno przeczytałem podręcznik Java SE 8 Programmer Guide ii.
Znalazłem coś na temat różnicy między
AutoCloseable
vsCloseable
.AutoCloseable
Interfejs został wprowadzony w Javie 7. Wcześniej inny interfejs o nazwie istniałyCloseable
. Był podobny do tego, czego chcieli projektanci języka, z następującymi wyjątkami:Closeable
ogranicza typ zgłaszanego wyjątkuIOException
.Closeable
wymaga, aby implementacje były idempotentne.Projektanci języka kładą nacisk na kompatybilność wsteczną. Ponieważ zmiana istniejącego interfejsu była niepożądana, stworzyli nowy o nazwie
AutoCloseable
. Ten nowy interfejs jest mniej rygorystyczny niżCloseable
. PonieważCloseable
spełnia wymaganiaAutoCloseable
, zaczął wdrażać,AutoCloseable
gdy ten ostatni został wprowadzony.źródło
Closeable
”, proponuję powiedzieć „Ten nowy interfejs może być używany w bardziej ogólnych kontekstach, w których wyjątek zgłaszany podczas zamykania niekoniecznie jest IOException”. W świecie Java bycie „mniej rygorystycznym” ma negatywny wpływ na to.