1. Tashqi resurslar
Ba'zan Java dasturi o'z ish jarayonida Java-mashinadan tashqaridagi obyektlar bilan o'zaro aloqada bo'ladi. Masalan, diskdagi fayllar bilan. Bunday obyektlar odatda tashqi resurslar deb ataladi. Ichki resurslar — bu Java-mashinada yaratilgan obyektlar.
Odatda o'zaro aloqa quyidagi sxema bo'yicha sodir bo'ladi:

Resurslarni hisobga olish
Operatsion tizim mavjud resurslarni qat'iy hisobga oladi va ularga turli dasturlar tomonidan birgalikda kirishni nazorat qiladi. Masalan, agar bitta dastur faylni o'zgartirsa, boshqa dastur bu faylni o'zgartira (yoki o'chira) olmaydi. Bu faqat fayllarga tegishli emas, lekin ularning misolida eng yaxshi tushuniladi.
Operatsion tizimda dasturga biror resursni egallash va/yoki bo'shatish imkonini beruvchi funksiyalar (API) mavjud. Agar resurs band bo'lsa, u bilan faqat ushbu resursni egallagan dastur ishlashi mumkin. Agar resurs bo'sh bo'lsa, har qanday dastur uni egallashi mumkin.
Tasavvur qiling, ofisingizda umumiy krujkalar bor. Agar biror kishi krujkani olsa, boshqasi uni olmaydi. Lekin agar undan foydalanganlar, yuvganlar va joyiga qo'ygan bo'lsalar, uni yana har qanday kishi olish mumkin yoki metroda yoki marshrutkada joylar. Agar joy bo'sh bo'lsa — har kim uni egallashi mumkin. Agar joy band bo'lsa — ularni egallagan kishi tomonidan boshqariladi.
Tashqi resurslarni egallash
Har safar sizning Java-dasturingiz diskdagi biror fayl bilan ishlay boshlaganda, Java-mashina bu faylga operatsion tizimdan monopol kirishni so'raydi. Agar resurs bo'sh bo'lsa, Java-mashina uni egallaydi.
Lekin siz fayl bilan ishlashni tugatgandan so'ng, bu resursni (faylni) bo'shatish kerak: operatsion tizimga u sizga kerak emasligini xabardor qilish. Agar siz buni qilmasangiz, resurs hali ham sizning dasturingiz uchun hisobdagi bo'lishni davom etadi.
Har bir ishga tushirilgan dastur uchun operatsion tizim band qilingan resurslar ro'yxatini yuritadi. Agar sizning dasturingiz unga ruxsat etilgan resurslar limitini oshirib yuborsa, yangi resurslarni operatsion tizim sizga bermaydi.
Yaxshi yangilik shundaki, agar sizning dasturingiz tugasa, barcha resurslar avtomatik ravishda bo'shatiladi (buni operatsion tizimning o'zi qiladi).
Yomon yangilik shundaki, agar siz server dasturini yozayotgan bo'lsangiz (va ko'p server dasturlari Java-da yozilgan), sizning serveringiz kunlar, haftalar, oylab ishlashi kerak to'xtovsiz. Va agar siz kuniga 100 ta fayl ochsangiz va ularni yopmasangiz, bir necha hafta o'tgach, sizning dasturingiz o'z limitini tugatadi va yiqiladi. Bu barqaror ishning oylari kabi ko'rinmaydi, to'g'rimi?
2. close() metodi
Tashqi resurslarni ishlatadigan klasslar uchun ulardan foydalanishni to'xtatish uchun maxsus metod mavjud — close().
Quyida faylga nimadir yozadigan va uni yopadigan dastur misoli berilgan – operatsion tizim resurslarini bo'shatadi. Bu taxminan shunday ko'rinadi:
| Kod | Izoh |
|---|---|
|
Faylga yo'l. Fayl obyektini olamiz: resursni egallaymiz. Faylga yozamiz Faylni yopamiz — resursni bo'shatamiz |
Fayl bilan (yoki boshqa tashqi resurs bilan) ishlashdan so'ng siz tashqi resurs bilan bog'liq obyektga close() metodini chaqirishingiz kerak.
Istisnolar
Hammasi oddiydek ko'rinadi. Ammo dastur ishlash jarayonida istisnolar yuzaga kelishi mumkin va tashqi resurs bo'shatilmay qoladi. Bu juda yomon.
Har doim close() metodi qo'ng'iroq qilinishi uchun kodimizni try-catch-finally blokiga o'rashimiz va final blokiga close() metodini qo'shishimiz kerak. Bu taxminan shunday ko'rinadi:
try
{
FileOutputStream output = new FileOutputStream(path);
output.write(1);
output.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
output.close();
}
Bu kod kompilyatsiya qilinmaydi, chunki output o'zgaruvchisi try {} blokida e'lon qilingan va shu tufayli finally blokida ko'rinmaydi.
To'xtatamiz:
FileOutputStream output = new FileOutputStream(path);
try
{
output.write(1);
output.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
output.close();
}
Yaxshi, lekin FileOutputStream obyektini yaratishda xato yuzaga kelgan bo'lsa, u ishlamaydi va bu juda oson sodir bo'lishi mumkin.
To'xtatamiz:
FileOutputStream output = null;
try
{
output = new FileOutputStream(path);
output.write(1);
output.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
output.close();
}
Hali ham bir necha izohlar mavjud. Birinchidan, agar FileOutputStream obyektini yaratishda xato yuzaga kelsa, output o'zgaruvchisi null bo'ladi va bu faktni finally blokida e'tiborga olish kerak.
Ikkinchidan, close() metodi har doim finally blokida chaqiriladi, shuning uchun u try blokida kerak emas. Yakuniy kod shunday ko'rinadi:
FileOutputStream output = null;
try
{
output = new FileOutputStream(path);
output.write(1);
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (output != null)
output.close();
}
Hatto catch blokini hisobga olmasak ham, 3 satrli kodimiz 10 satrga aylandi. Garchi aslida biz faqat faylni ochib, unga 1 yozdik. Biroz murakkab, shunday emasmi?
3. try-with-resources
Java yaratuvchilari bizga sintaktik shakarni ham qo'shdilar. Java 7-versiyasidan boshlab, unda yangi try-with-resources (try bilan resurslar) operatori paydo bo'ldi.
Bu aynan close() metodini majburiy chaqirish muammosini hal qilish uchun yaratilgan. Umumiy tarzda u juda sodda ko'rinadi:
try (Klass nom = new Klass())
{
Kod, o'zgaruvchi nom bilan ishlaydi
}
Bu operator try-ning yana bir turi. try kalit so'zidan keyin dumaloq qavslarni qo'shish kerak, va ular ichida — tashqi resurslar bilan obyektlarni yaratish kerak. Dumaloq qavsda ko'rsatilgan obyekt uchun kompilyator o'zi finally seksiyasini va close() metodini qo'shadi.
Quyida ikki teng misol keltirilgan:
| Uzun kod | try-with-resources kod |
|---|---|
|
|
try-with-resources ishlatishni ko'rsatadigan kod ancha qisqa va o'qilishi osonroq. Va kod kam bo'lsa, xatolik yoki xato qilish imkoniyati kamayadi.
Aytgancha, try-with-resources operatoriga catch va finally bloklarini qo'shish mumkin. Agar ularga ehtiyoj bo'lmasa, ularni qo'shmaslik ham mumkin.
4. Bir nechta o'zgaruvchilar bir vaqtning o'zida
Aytgancha, tez-tez bir vaqtning o'zida bir nechta fayllarni ochish kerak bo'lgan vaziyat yuzaga kelishi mumkin. Aytaylik, siz faylni nusxa olmoqdasiz va sizga ikkita obyekt kerak: ma'lumotlarni nusxalab oladigan fayl va ma'lumotlarni nusxa ko'chiradigan fayl.
Bunday holatda try-with-resources operatoriga bir necha obyekt yaratishga ruxsat beriladi. Ob'ektlarni yaratish kodi nuqta-vergul bilan ajratilishi kerak. Buyruqining umumiy ko'rinishi:
try (Klass nom = new Klass(); Klass2 nom2 = new Klass2())
{
Kod, nom va nom2 o'zgaruvchilari bilan ishlaydi
}
Fayllarni nusxalash misoli:
| Uzun kod | Qisqa kod |
|---|---|
|
|
Umuman olganda, shuni aytish joiz: ajoyib narsa — try-with-resources
5. AutoCloseable interfeysi
Lekin bu hali hammasi emas. Diqqatli o'quvchi darhol ushbu operatorning qo'llanish doirasi hiylasini izlay boshlaydi.
Agar klassda close() metodi bo'lmasa, try-with-resources operatori qanday ishlaydi? Ehtimol, hech narsa chaqirilmaydi. Metod bo'lmasa, muammo yo'q.
Agar klassda bir nechta close() metodlari bo'lsa va ularga parametrlar o'tkazilishi kerak bo'lsa, try-with-resources qanday ishlaydi? Va agar klassda parametrisiz close() metodi bo'lmasa?
Umid qilamanki, siz haqiqatan ham ushbu savollarni berdingiz va ehtimol faqat ularni emas.
Bunday savollarni bartaraf etish uchun Java yaratuvchilari maxsus klass (interfeys) AutoCloseable ni o'ylab topishdi, unda faqat bitta metod — parametrisiz close() mavjud.
Shuningdek, resurslar sifatida qabul qilinganda try-with-resources faqat AutoCloseable dan meros olgan klass obyektlarini qabul qilish mumkin cheklovini qo'shdilar. Shunday qilib, ushbu obyektlarda har doim parametrisiz close() metodi bo'ladi.
Aytgancha, sizningcha, try-with-resources ga parametrisiz close() metodiga ega lekin AutoCloseable dan meros olmagan klass obyekti resurs sifatida o'tkazilishi mumkinmi?
Yomon yangilik: to'g'ri javob — yo'q, klasslar albatta AutoCloseable interfeysini amalga oshirishi kerak.
Yaxshi yangilik: Java da juda ko'p klasslar ushbu interfeysni amalga oshiradi, shuning uchun katta ehtimol bilan hamma narsa kerakli tarzda ishlaydi.
GO TO FULL VERSION