1. Sumber daya eksternal
Saat program Java berjalan, terkadang ia berinteraksi dengan entitas di luar mesin Java. Misalnya, dengan file di disk. Entitas ini biasanya disebut sumber daya eksternal. Sumber daya internal adalah objek yang dibuat di dalam mesin Java.
Biasanya, interaksi mengikuti skema ini:
Sumber daya pelacakan
Sistem operasi dengan ketat melacak sumber daya yang tersedia, dan juga mengontrol akses bersama ke sumber daya tersebut dari berbagai program. Misalnya, jika satu program mengubah file, maka program lain tidak dapat mengubah (atau menghapus) file tersebut. Prinsip ini tidak terbatas pada file, tetapi memberikan contoh yang paling mudah dimengerti.
Sistem operasi memiliki fungsi (API) yang memungkinkan program memperoleh dan/atau melepaskan sumber daya. Jika sumber daya sibuk, maka hanya program yang memperolehnya yang dapat bekerja dengannya. Jika sumber daya gratis, maka program apa pun dapat memperolehnya.
Bayangkan kantor Anda telah berbagi cangkir kopi. Jika ada yang mengambil mug, maka orang lain tidak bisa lagi mengambilnya. Namun setelah mug tersebut digunakan, dicuci, dan diletakkan kembali pada tempatnya, maka siapapun dapat mengambilnya kembali. Situasi dengan tempat duduk di bus atau kereta bawah tanah adalah sama. Jika kursi gratis, maka siapa pun dapat mengambilnya. Jika kursi diduduki, maka itu dikendalikan oleh orang yang mengambilnya.
Memperoleh sumber daya eksternal .
Setiap kali program Java Anda mulai bekerja dengan file di disk, mesin Java meminta sistem operasi untuk akses eksklusif ke sana. Jika sumber dayanya gratis, maka mesin Java akan memperolehnya.
Tetapi setelah Anda selesai bekerja dengan file tersebut, sumber daya (file) ini harus dirilis, yaitu Anda perlu memberi tahu sistem operasi bahwa Anda tidak lagi membutuhkannya. Jika Anda tidak melakukan ini, sumber daya akan terus disimpan oleh program Anda.
Sistem operasi menyimpan daftar sumber daya yang ditempati oleh setiap program yang sedang berjalan. Jika program Anda melebihi batas sumber daya yang ditetapkan, sistem operasi tidak akan lagi memberi Anda sumber daya baru.
Kabar baiknya adalah jika program Anda dihentikan, semua sumber daya dilepaskan secara otomatis (sistem operasi itu sendiri yang melakukannya).
Kabar buruknya adalah jika Anda sedang menulis aplikasi server (dan banyak aplikasi server yang ditulis dalam Java), server Anda harus dapat berjalan selama berhari-hari, berminggu-minggu, dan berbulan-bulan tanpa henti. Dan jika Anda membuka 100 file sehari dan tidak menutupnya, maka dalam beberapa minggu aplikasi Anda akan mencapai batas sumber daya dan macet. Itu jauh dari pekerjaan stabil selama berbulan-bulan.
2. close()
metode
Kelas yang menggunakan sumber daya eksternal memiliki metode khusus untuk melepaskannya: close()
.
Di bawah ini kami memberikan contoh program yang menulis sesuatu ke file dan kemudian menutup file setelah selesai, yaitu membebaskan sumber daya sistem operasi. Ini terlihat seperti ini:
Kode | Catatan |
---|---|
|
Jalur ke file. Dapatkan objek file: dapatkan sumber daya. Tulis ke file Tutup file - lepaskan sumber daya |
Setelah bekerja dengan file (atau sumber daya eksternal lainnya), Anda harus memanggil close()
metode pada objek yang ditautkan ke sumber daya eksternal.
Pengecualian
Semuanya tampak sederhana. Namun pengecualian dapat terjadi saat program berjalan, dan sumber daya eksternal tidak akan dirilis. Dan itu sangat buruk.
Untuk memastikan bahwa close()
metode selalu dipanggil, kita perlu membungkus kode kita dalam blok try
- catch
- finally
dan menambahkan close()
metode ke finally
blok tersebut. Ini akan terlihat seperti ini:
try
{
FileOutputStream output = new FileOutputStream(path);
output.write(1);
output.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
output.close();
}
Kode ini tidak dapat dikompilasi, karena output
variabel dideklarasikan di dalam try {}
blok, dan karenanya tidak terlihat di finally
blok.
Mari kita perbaiki:
FileOutputStream output = new FileOutputStream(path);
try
{
output.write(1);
output.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
output.close();
}
Tidak apa-apa, tetapi tidak akan berfungsi jika terjadi kesalahan saat kita membuat objek FileOutputStream
, dan ini bisa terjadi dengan mudah.
Mari kita perbaiki:
FileOutputStream output = null;
try
{
output = new FileOutputStream(path);
output.write(1);
output.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
output.close();
}
Masih ada beberapa kritik. Pertama, jika terjadi kesalahan saat membuat FileOutputStream
objek, maka output
variabelnya akan menjadi nol. Kemungkinan ini harus diperhitungkan dalam finally
blok.
Kedua, close()
metode ini selalu dipanggil di dalam finally
blok, yang artinya tidak diperlukan di dalam try
blok. Kode terakhir akan terlihat seperti ini:
FileOutputStream output = null;
try
{
output = new FileOutputStream(path);
output.write(1);
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (output != null)
output.close();
}
Bahkan jika kita tidak mempertimbangkan catch
blok, yang dapat dihilangkan, maka 3 baris kode kita menjadi 10. Tapi pada dasarnya kita hanya membuka file dan menulis 1. Agak rumit, bukan begitu?
3. try
-dengan-sumber daya
Dan di sini pencipta Java memutuskan untuk menaburkan gula sintaksis pada kami. Dimulai dengan versi ke-7, Java memiliki try
pernyataan -with-resources baru.
Itu dibuat tepat untuk memecahkan masalah dengan panggilan wajib ke close()
metode tersebut. Kasus umum terlihat cukup sederhana:
try (ClassName name = new ClassName())
{
Code that works with the name variable
}
Ini adalah variasi lain dari try
pernyataan tersebut . Anda perlu menambahkan tanda kurung setelah try
kata kunci, lalu membuat objek dengan sumber daya eksternal di dalam tanda kurung. Untuk setiap objek dalam tanda kurung, kompiler menambahkan sebuah finally
bagian dan panggilan ke close()
metode.
Di bawah ini adalah dua contoh yang setara:
Kode panjang | Kode dengan coba-dengan-sumber daya |
---|---|
|
|
Kode yang menggunakan try
-with-resources jauh lebih pendek dan lebih mudah dibaca. Dan semakin sedikit kode yang kita miliki, semakin kecil kemungkinan salah ketik atau kesalahan lainnya.
Ngomong-ngomong, kita bisa menambah catch
dan finally
memblokir try
pernyataan -with-resources. Atau Anda tidak dapat menambahkannya jika tidak diperlukan.
4. Beberapa variabel sekaligus
Omong-omong, Anda mungkin sering menghadapi situasi ketika Anda perlu membuka beberapa file secara bersamaan. Katakanlah Anda sedang menyalin file, jadi Anda memerlukan dua objek: file tempat Anda menyalin data dan file tempat Anda menyalin data.
Dalam hal ini, try
pernyataan -with-resources memungkinkan Anda membuat satu tetapi beberapa objek di dalamnya. Kode yang membuat objek harus dipisahkan dengan titik koma. Inilah tampilan umum dari pernyataan ini:
try (ClassName name = new ClassName(); ClassName2 name2 = new ClassName2())
{
Code that works with the name and name2 variables
}
Contoh menyalin file:
Kode panjang | Kode pendek |
---|---|
|
|
Nah, apa yang bisa kita katakan di sini? try
-dengan-sumber daya adalah hal yang luar biasa!
5. AutoCloseable
antarmuka
Tapi itu belum semuanya. Pembaca yang penuh perhatian akan segera mulai mencari jebakan yang membatasi bagaimana pernyataan ini dapat diterapkan.
Tapi bagaimana try
cara kerja pernyataan -with-resources jika kelas tidak memiliki close()
metode? Nah, misalkan tidak ada yang akan dipanggil. Tidak ada metode, tidak ada masalah.
Tetapi bagaimana try
cara kerja pernyataan -with-resources jika kelas memiliki beberapa close()
metode? Dan mereka membutuhkan argumen untuk disampaikan kepada mereka? Dan kelas tidak memiliki close()
metode tanpa parameter?
Saya harap Anda benar-benar bertanya pada diri sendiri pertanyaan-pertanyaan ini, dan mungkin yang lainnya.
Untuk menghindari masalah seperti itu, pembuat Java membuat antarmuka khusus bernama AutoCloseable
, yang hanya memiliki satu metode — close()
, yang tidak memiliki parameter.
Mereka juga menambahkan batasan bahwa hanya objek dari kelas yang diimplementasikanAutoCloseable
yang dapat dideklarasikan sebagai resource dalam try
pernyataan -with-resources. Akibatnya, objek seperti itu akan selalu memiliki close()
metode tanpa parameter.
Omong-omong, menurut Anda apakah try
pernyataan -with-resources dapat dideklarasikan sebagai sumber daya sebuah objek yang kelasnya memiliki close()
metode sendiri tanpa parameter tetapi tidak diimplementasikan AutoCloseable
?
Berita buruknya: Jawaban yang benar adalah tidak — kelas harus mengimplementasikan AutoCloseable
antarmuka.
Kabar baiknya: Java memiliki banyak kelas yang mengimplementasikan antarmuka ini, jadi kemungkinan besar semuanya akan berfungsi sebagaimana mestinya.
GO TO FULL VERSION