CodeGym /Kurslar /Java SELF AZ /try with resources operatoru

try with resources operatoru

Java SELF AZ
Səviyyə , Dərs
Mövcuddur

1. Əlavə resurslar

Bəzən Java-proqram işləyərkən Java-maşınından kənarda olan obyektlərlə qarşılıqlı əlaqədə olur. Məsələn, diskdəki fayllarla. Belə obyektlər adətən əlavə resurslar adlanır. Daxili resurslar - Java-maşını daxilində yaradılan obyektlərdir.

Adətən qarşılıqlı əlaqə aşağıdakı sxemlə həyata keçirilir:

Try with resources operatoru

Resursların uçotu

Əməliyyat sistemi mövcud resursların ciddi uçotunu aparır, həmçinin müxtəlif proqramların onlara birgə müraciətinə nəzarət edir. Məsələn, əgər bir proqram hansısa faylı dəyişirsə, başqa bir proqram həmin faylı dəyişə (və ya silə) bilməz. Bu yalnız fayllara aid deyil, lakin onları nümunə kimi götürmək daha aydın olar.

Əməliyyat sistemində proqramlara hansısa resursu tutmaq və/və ya azad etmək imkanı verən funksiyalar (API) mövcuddur. Əgər resurs tutulubsa, onu yalnız tutmuş proqram istifadə edə bilər. Əgər resurs azaddırsa, istənilən proqram onu tuta bilər.

Təsəvvür edin ki, ofisdə ümumi fincanlar var. Kimsə bir fincanı götürəndə, artıq başqa biri onu götürə bilməz. Amma istifadə edib, yuyub yerinə qoyandan sonra, artıq onu kim istəsə götürə bilər. Və ya metroda və ya marşrutkada yer. Əgər yer azaddırsa, istənilən şəxs onu tuta bilər. Əgər yer tutulubsa, artıq yalnız onu tutan şəxs nəzarət edir.

Əlavə resursların tutulması

Java-proqramınız hər dəfə diskdəki hansısa faylla işləməyə başladıqda, Java-maşını əməliyyat sistemindən bu fayla müstəsna giriş istəyir. Əgər resurs azaddırsa, onu Java-maşını tutur.

Ama faylla işinizi bitirdikdən sonra, həmin resursu (faylı) azad etmək lazımdır: əməliyyat sisteminə bildirmək lazımdır ki, artıq o sizə lazım deyil. Əgər bunu etməsəniz, resurs proqramınıza aid olaraq qalmağa davam edəcək.

Əməliyyat sistemi işləyən hər bir proqram üçün tutulan resursların siyahısını aparır. Əgər proqramınız ona verilən resurs limitini aşsa, artıq yeni resurslar əməliyyat sistemi tərəfindən sizə verilməyəcək.

Yaxşı xəbər odur ki, əgər proqramınız başa çatarsa, bütün resurslar avtomatik olaraq azad edilir (bunu əməliyyat sistemi özü edir).

Pis xəbər isə odur ki, əgər siz server tətbiqi yazırsınızsa (və bir çox server tətbiqləri Java-da yazılır), sizin serveriniz günlərlə, həftələrlə, aylarla fasiləsiz işləməlidir. Və əgər gün ərzində 100 fayl açıb onları bağlamırsınızsa, bir neçə həftə sonra tətbiqiniz öz limitini aşacaq və dayanacaq. Bu isə aylarla stabil işləyən sistemə oxşamır.


2. close() metodu

Xarici resurslardan istifadə edən siniflərin, onları azad etmək üçün xüsusi bir metodu var — close().

Aşağıda fayla nəsə yazıb sonra faylı bağlayan bir proqram nümunəsi verilmişdir – əməliyyat sisteminin resurslarını azad edir. Təxminən belə görünür:

Kod Qeyd
String path = "c:\\projects\\log.txt";
FileOutputStream output = new FileOutputStream(path); output.write(1);
output.close();
Faylın yolu.
Fayl obyektini alırıq: resursu götürürük.
Fayla yazırıq
Faylı bağlayırıq — resursu azad edirik.

Faylla (və ya digər xarici resurslarla) işlədikdən sonra, xarici resursla əlaqəli olan obyektin close() metodunu çağırmalısınız.

İstisnalar

Hər şey sadə görünür. Amma proqram işləyərkən istisnalar yarana bilər və xarici resurs heç bir zaman azad olunmaz. Bu, çox pisdir.

close() metodu həmişə çağırılsın deyə, kodumuzu try-catch-finally blokuna yığıb, close() metodunu finally blokuna əlavə etmək lazımdır. Bu şəkildə görünəcək:

try
{
   FileOutputStream output = new FileOutputStream(path);
   output.write(1);
   output.close();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   output.close();
}

Bu kod kompilyasiya olunmayacaq, çünki output dəyişəni try {} blokunda elan edilib, bu səbəbdən finally blokunda görünmür.

Düzəldirik:

FileOutputStream output = new FileOutputStream(path);

try
{
   output.write(1);
   output.close();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   output.close();
}

Yaxşı, amma işləməyəcək, əgər FileOutputStream obyekti yaradılarkən bir səhv baş versə, bu, çox asanlıqla ola bilər.

Yenidən düzəliş edirik:

FileOutputStream output = null;

try
{
   output = new FileOutputStream(path);
   output.write(1);
   output.close();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   output.close();
}

Hələ də bir neçə qeyd var. Birincisi, əgər FileOutputStream obyekti yaradılarkən bir səhv baş versə, output dəyişəni null olacaq və bu faktı finally blokunda nəzərə almaq lazımdır.

İkincisi, finally blokunda olan close() metodu həmişə çağırılır, buna görə də try blokunda ona ehtiyac yoxdur. Son kod belə görünəcək:

FileOutputStream output = null;

try
{
   output = new FileOutputStream(path);
   output.write(1);
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   if (output != null)
      output.close();
}

Əgər catch blokunu nəzərə almasaq belə, kodumuz üç sətirdən 10 sətirə çevrildi. Halbuki əslində biz sadəcə faylı açıb oraya 1 yazdıq. Bir qədər həcmli deyilmi?


3. try-with-resources

Java-nı yaradanlar bu yerdə də bir az sintaktik "şirinlik" əlavə etməyə qərar verdilər. Java 7-ci versiyasından başlayaraq, bu yeni try-with-resources (try ilə resurslar) operatoru əlavə olundu.

Bu operator, əsasən, close() metodunun çağırılması problemini həll etmək üçün yaradılıb. Əsas görünüşü belədir:

try (Sinif ad = new Sinif())
{
     Dəyişənlə işləyən kod ad
}

Bu, operator try-nin başqa bir variantıdır. try açar sözündən sonra dairəvi mötərizələr əlavə etməlisiniz və onların içərisində xarici resurslarla obyektlər yaratmalısınız. Dairəvi mötərizələrdə göstərilən obyekt üçün kompilyator özü finally bölməsi və close() metodunun çağırılmasını əlavə edəcək.

Aşağıda iki ekvivalent nümunə göstərilib:

Uzun kod try-with-resources ilə kod
FileOutputStream output = null;

try
{
   output = new FileOutputStream(path);
   output.write(1);
}
finally
{
   if (output != null)
   output.close();
}
try(FileOutputStream output = new FileOutputStream(path))
{
   output.write(1);
}

try-with-resources istifadəsi ilə kod daha qısa və oxunaqlıdır. Və nə qədər az kod varsa, səhv etmək şansı bir o qədər azdır.

Bununla yanaşı, try-with-resources operatoruna catchfinally blokları əlavə etmək mümkündür. Onları əlavə etmək məcburi deyil, əgər ehtiyac yoxdursa.



4. Bir neçə dəyişəni eyni anda istifadə etmək

Məsələn, belə bir vəziyyət meydana çıxa bilər ki, birdən çox faylı eyni anda açmağa ehtiyacınız var. Tutaq ki, bir faylı kopyalayırıq və sizə iki obyekt lazımdır: məlumatları kopyaladığınız fayl və məlumatları kopyaladığınız fayl.

Bu hal üçün try-with-resources operatoru bir obyekt deyil, bir neçə obyekt yaratmağa icazə verir. Obyektlərin yaradılma kodu nöqtəli vergül ilə ayrılmalıdır. Ümumi görünüşü belədir:

try (Class name = new Class(); Class2 name2 = new Class2())
{
   namename2 dəyişəni ilə işləyən kod
}

Faylların kopyalanmasının nümunəsi:

Uzun kod Qısa kod
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

FileInputStream input = null;
FileOutputStream output = null;

try
{
   input = new FileInputStream(src);
   output = new FileOutputStream(dest);

   byte[] buffer = input.readAllBytes();
   output.write(buffer);
}
finally
{
   if (input != null)
      input.close();
   if (output != null)
      output.close();
}
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileInputStream input = new FileInputStream(src);

FileOutputStream output = new FileOutputStream(dest))
{
   byte[] buffer = input.readAllBytes();
   output.write(buffer);
}

Ümumilikdə, nə deyək: bu try-with-resources çox əla bir şeydir.


5. AutoCloseable interfeysi

Amma hələ də hamısı bu deyil. Diqqətli oxucu dərhal bu operatorun tətbiq hüdudunda bir şübhə axtaracaq.

Bəs əgər sinifdə close() metodu yoxdursa, try-with-resources operatoru necə işləyəcək? Yaxşı, onda heç nə çağırılmayacaq. Metod yoxdursa, problem də yoxdur.

Bəs əgər sinifin bir neçə close() metodu varsa? Və onlara parametrlər ötürmək lazımdır? Və əgər sinifin parametrsiz close() metodu yoxdursa?

Ümid edirəm ki, siz həqiqətən bu sualları özünüzə verdiniz, və bəlkə də daha çoxunu da.

Bu cür sualların olmaması üçün Java-nın yaradıcıları xüsusi bir sinif (interfeys) AutoCloseable fikirləşiblər ki, burada yalnız bir metod var – parametrlərsiz close().

Həmçinin məhdudlaşdırma da əlavə olunub ki, try-with-resources daxilində resurs olaraq yalnız AutoCloseable-dan irəli gələn siniflərin obyektlərini istifadə etmək olar. Beləliklə, bu obyektlərin həmişə parametrlərsiz close() metodu olacaq.

Bu arada, sizcə, resurs kimi sinfin parametrlərsiz close() metodu olan, amma AutoCloseable-dan irəli gəlməyən obyektini try-with-resources daxilində istifadə etmək olarmı?

Pis xəbər: doğru cavab – yox, siniflər mütləq AutoCloseable interfeysini reallaşdırmalıdır.

Yaxşı xəbər: Java-da çox sayda sinif bu interfeysi reallaşdırır, beləliklə, yüksək ehtimalla hər şey lazım olduğu kimi işləyəcək.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION