Σε αυτό το σεμινάριο, θα μάθουμε για τη δήλωση δοκιμής με πόρους για να κλείσουμε αυτόματα τους πόρους.
Η try-with-resources
δήλωση κλείνει αυτόματα όλους τους πόρους στο τέλος της δήλωσης. Ένας πόρος είναι ένα αντικείμενο που πρέπει να κλείσει στο τέλος του προγράμματος.
Η σύνταξή του είναι:
try (resource declaration) ( // use of the resource ) catch (ExceptionType e1) ( // catch block )
Όπως φαίνεται από την παραπάνω σύνταξη, δηλώνουμε τη try-with-resources
δήλωση από,
- δηλώνει και τεκμηριώνει τον πόρο εντός της
try
ρήτρας. - καθορίζοντας και χειρίζοντας όλες τις εξαιρέσεις που ενδέχεται να απορριφθούν κατά το κλείσιμο του πόρου.
Σημείωση: Η δήλωση δοκιμής με πόρους κλείνει όλους τους πόρους που εφαρμόζουν τη διεπαφή AutoCloseable.
Ας πάρουμε ένα παράδειγμα που εφαρμόζει τη try-with-resources
δήλωση.
Παράδειγμα 1: δοκιμάστε με πόρους
import java.io.*; class Main ( public static void main(String() args) ( String line; try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) ( while ((line = br.readLine()) != null) ( System.out.println("Line =>"+line); ) ) catch (IOException e) ( System.out.println("IOException in try block =>" + e.getMessage()); ) ) )
Έξοδος εάν το αρχείο test.txt δεν βρεθεί.
IOException στο try-with-resources block => test.txt (Δεν υπάρχει τέτοιο αρχείο ή κατάλογος)
Έξοδος αν βρεθεί το αρχείο test.txt.
Εισαγωγή της γραμμής δοκιμής με πόρους block => test line
Σε αυτό το παράδειγμα, χρησιμοποιούμε μια παρουσία του BufferedReader για να διαβάσουμε δεδομένα από το test.txt
αρχείο.
Η δήλωση και η παρουσίαση του BufferedReader μέσα στη try-with-resources
δήλωση διασφαλίζει ότι η παρουσία της είναι κλειστή ανεξάρτητα από το αν η try
δήλωση ολοκληρώνεται κανονικά ή ρίχνει μια εξαίρεση.
Εάν προκύψει εξαίρεση, μπορεί να αντιμετωπιστεί χρησιμοποιώντας τα μπλοκ χειρισμού εξαιρέσεων ή τη λέξη-κλειδί ρίψεων.
Καταπιεσμένες εξαιρέσεις
Στο παραπάνω παράδειγμα, εξαιρέσεις μπορούν να απορριφθούν από τη try-with-resources
δήλωση όταν:
- Το αρχείο
test.txt
δεν βρέθηκε. - Κλείσιμο του
BufferedReader
αντικειμένου.
Μια εξαίρεση μπορεί επίσης να απορριφθεί από το try
μπλοκ καθώς η ανάγνωση ενός αρχείου μπορεί να αποτύχει για πολλούς λόγους ανά πάσα στιγμή.
Εάν ρίχνονται εξαιρέσεις τόσο από το try
μπλοκ όσο και από τη try-with-resources
δήλωση, η εξαίρεση από το try
μπλοκ ρίχνεται και η εξαίρεση από τη try-with-resources
δήλωση καταργείται.
Ανάκτηση κατασταλμένων εξαιρέσεων
Στην Java 7 και μεταγενέστερες εκδόσεις, οι κατασταλμένες εξαιρέσεις μπορούν να ανακτηθούν καλώντας τη Throwable.getSuppressed()
μέθοδο από την εξαίρεση που ρίχνεται από το try
μπλοκ.
Αυτή η μέθοδος επιστρέφει έναν πίνακα όλων των εξαιρούμενων εξαιρέσεων. Παίρνουμε τις κατασταλμένες εξαιρέσεις στο catch
μπλοκ.
catch(IOException e) ( System.out.println("Thrown exception=>" + e.getMessage()); Throwable() suppressedExceptions = e.getSuppressed(); for (int i=0; i" + suppressedExceptions(i)); ) )
Πλεονεκτήματα της χρήσης δοκιμαστικών πόρων
Ακολουθούν τα πλεονεκτήματα της χρήσης του try-with-resources:
1. επιτέλους μπλοκ δεν απαιτείται για να κλείσετε τον πόρο
Πριν από την εισαγωγή του Java 7 σε αυτήν τη δυνατότητα, έπρεπε να χρησιμοποιήσουμε το finally
μπλοκ για να διασφαλίσουμε ότι ο πόρος είναι κλειστός για να αποφευχθούν διαρροές πόρων.
Ακολουθεί ένα πρόγραμμα παρόμοιο με το Παράδειγμα 1 . Ωστόσο, σε αυτό το πρόγραμμα, χρησιμοποιήσαμε επιτέλους μπλοκ για κλείσιμο πόρων.
Παράδειγμα 2: Κλείσιμο πόρου χρησιμοποιώντας τελικά μπλοκ
import java.io.*; class Main ( public static void main(String() args) ( BufferedReader br = null; String line; try ( System.out.println("Entering try block"); br = new BufferedReader(new FileReader("test.txt")); while ((line = br.readLine()) != null) ( System.out.println("Line =>"+line); ) ) catch (IOException e) ( System.out.println("IOException in try block =>" + e.getMessage()); ) finally ( System.out.println("Entering finally block"); try ( if (br != null) ( br.close(); ) ) catch (IOException e) ( System.out.println("IOException in finally block =>"+e.getMessage()); ) ) ) )
Παραγωγή
Είσοδος try block Line => line from test.txt file Είσοδος τελικά block
Όπως μπορούμε να δούμε από το παραπάνω παράδειγμα, η χρήση του finally
μπλοκ για την εκκαθάριση πόρων καθιστά τον κώδικα πιο περίπλοκο.
Παρατηρήστε επίσης το try… catch
μπλοκ στο finally
μπλοκ; Αυτό συμβαίνει επειδή IOException
μπορεί επίσης να προκύψει κατά το κλείσιμο της BufferedReader
παρουσίας μέσα σε αυτό το finally
μπλοκ, ώστε να πιάσει και να χειριστεί επίσης.
Η try-with-resources
δήλωση κάνει αυτόματη διαχείριση πόρων . Δεν χρειάζεται να κλείσουμε ρητά τους πόρους καθώς η JVM τους κλείνει αυτόματα. Αυτό κάνει τον κώδικα πιο ευανάγνωστο και ευκολότερο να γραφτεί.
2. δοκιμάστε με πόρους με πολλούς πόρους
Μπορούμε να δηλώσουμε περισσότερους από έναν πόρους στη try-with-resources
δήλωση διαχωρίζοντάς τους με ερωτηματικό;
Παράδειγμα 3: δοκιμάστε με πολλούς πόρους
import java.io.*; import java.util.*; class Main ( public static void main(String() args) throws IOException( try (Scanner scanner = new Scanner(new File("testRead.txt")); PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) ( while (scanner.hasNext()) ( writer.print(scanner.nextLine()); ) ) ) )
Εάν αυτό το πρόγραμμα εκτελείται χωρίς να δημιουργηθούν εξαιρέσεις, το Scanner
αντικείμενο διαβάζει μια γραμμή από το testRead.txt
αρχείο και το γράφει σε ένα νέο testWrite.txt
αρχείο.
Όταν γίνονται πολλές δηλώσεις, η try-with-resources
δήλωση κλείνει αυτούς τους πόρους με αντίστροφη σειρά. Σε αυτό το παράδειγμα, το PrintWriter
αντικείμενο κλείνει πρώτα και μετά το Scanner
αντικείμενο είναι κλειστό.
Βελτίωση δοκιμών με πόρους Java 9
Στην Java 7, υπάρχει ένας περιορισμός στη try-with-resources
δήλωση. Ο πόρος πρέπει να δηλωθεί τοπικά εντός του μπλοκ του.
try (Scanner scanner = new Scanner(new File("testRead.txt"))) ( // code )
Εάν δηλώσαμε τον πόρο εκτός του μπλοκ στην Java 7, θα δημιουργούσε ένα μήνυμα σφάλματος.
Scanner scanner = new Scanner(new File("testRead.txt")); try (scanner) ( // code )
Για να αντιμετωπίσει αυτό το σφάλμα, η Java 9 βελτίωσε τη try-with-resources
δήλωση, έτσι ώστε η αναφορά του πόρου να μπορεί να χρησιμοποιηθεί ακόμη και αν δεν δηλώνεται τοπικά. Ο παραπάνω κώδικας θα εκτελεστεί χωρίς κανένα σφάλμα σύνταξης.