"Amigo, on kulübe!"

"Java öğrendiğim için mutluyum Kaptan!"

"Sakin ol Amigo. Bugün çok ilginç bir konumuz var. Bir Java programının dış kaynaklarla nasıl etkileşime girdiği hakkında konuşacağız ve çok ilginç bir Java deyimi üzerinde çalışacağız. Kulaklarınızı tıkamasanız iyi olur."

"Can kulağı ile dinliyorum."

"Bir Java programı çalışırken, bazen Java makinesinin dışındaki varlıklarla etkileşime girer. Örneğin, diskteki dosyalarla. Bu varlıklara genellikle harici kaynaklar denir."

"Öyleyse dahili kaynaklar olarak kabul edilenler nelerdir?"

"Dahili kaynaklar, Java makinesinin içinde oluşturulan nesnelerdir. Tipik olarak, etkileşim şu şemayı izler:

Kaynaklarla dene bildirimi

"İşletim sistemi, kullanılabilir kaynakları titizlikle takip eder ve ayrıca farklı programlardan bunlara paylaşılan erişimi denetler. Örneğin, bir program bir dosyayı değiştirirse, başka bir program o dosyayı değiştiremez (veya silemez). dosyalarla sınırlıdır, ancak en kolay anlaşılır örneği sağlarlar.

"İşletim sistemi, bir programın kaynakları almasına ve/veya serbest bırakmasına izin veren işlevlere (API'ler) sahiptir. Bir kaynak meşgulse, yalnızca onu alan program onunla çalışabilir. Bir kaynak ücretsizse, o zaman herhangi bir program edinebilir BT.

"Bir ofiste kahve kupalarını paylaştığınızı hayal edin. Birisi bir kupa alırsa, diğer insanlar onu artık alamaz. Ancak kupa kullanıldıktan, yıkandıktan ve yerine konduktan sonra herkes onu tekrar alabilir."

"Anladım. Metrodaki veya diğer toplu taşıma araçlarındaki koltuklar gibi. Bir koltuk boşsa, o zaman herkes onu alabilir. Bir koltuk doluysa, o zaman onu alan kişi tarafından kontrol edilir."

"Doğru. Şimdi de harici kaynakları elde etmekten bahsedelim . Java programınız diskteki bir dosyayla her çalışmaya başladığında, Java makinesi işletim sisteminden ona özel erişim ister. Kaynak ücretsizse, Java makinesi harici kaynakları alır. BT.

"Fakat dosyayla çalışmayı bitirdikten sonra, bu kaynak (dosya) serbest bırakılmalıdır, yani işletim sistemine artık ihtiyacınız olmadığını bildirmeniz gerekir. Bunu yapmazsanız, kaynak kullanılmaya devam edecektir . programınız tarafından tutulur."

"Kulağa adil geliyor."

"İşletim sistemi, bu şekilde kalması için çalışan her program tarafından kullanılan kaynakların bir listesini tutar. Programınız atanan kaynak sınırını aşarsa, işletim sistemi artık size yeni kaynaklar vermez.

"Tüm belleği yiyebilen programlar gibi..."

"Bunun gibi bir şey. İyi haber şu ki, programınız sona ererse, tüm kaynaklar otomatik olarak serbest bırakılır (bunu işletim sisteminin kendisi yapar).

"Eğer bu iyi haberse, bu kötü haberlerin olduğu anlamına mı geliyor?"

"Kesinlikle öyle. Kötü haber şu ki, eğer bir sunucu uygulaması yazıyorsan..."

"Ama ben böyle uygulamalar yazar mıyım?"

"Pek çok sunucu uygulaması Java ile yazılmıştır, bu yüzden büyük olasılıkla bunları iş için yazacaksınız. Dediğim gibi, bir sunucu uygulaması yazıyorsanız, o zaman sunucunuzun günlerce, haftalarca, aylarca kesintisiz çalışması gerekir. vesaire."

"Başka bir deyişle, program sonlanmıyor ve bu, belleğin otomatik olarak serbest bırakılmadığı anlamına geliyor."

"Kesinlikle. Ve eğer günde 100 dosya açar ve onları kapatmazsanız, birkaç hafta içinde uygulamanız kaynak sınırına ulaşacak ve çökecektir."

"Bu, aylar süren istikrarlı çalışmanın çok gerisinde kalıyor! Ne yapılabilir?"

"Dış kaynakları kullanan sınıfların, onları serbest bırakmak için özel bir yöntemi vardır: close().

"İşte bir dosyaya bir şeyler yazan ve bittiğinde dosyayı kapatan, yani işletim sisteminin kaynaklarını serbest bırakan bir program örneği. Kabaca şöyle görünüyor:

kod Not
String path = "c:\\projects\\log.txt";
FileOutputStream output = new FileOutputStream(path);
output.write(1);
output.close();
Dosyanın yolu.
Dosya nesnesini alın: kaynağı edinin.
Dosyaya yaz
Dosyayı kapat - kaynağı serbest bırak

close()"Ah... Yani, bir dosyayla (veya diğer harici kaynaklarla) çalıştıktan sonra, harici kaynağa bağlı nesne üzerindeki yöntemi çağırmam gerekiyor ."

"Evet. Her şey basit görünüyor. Ancak bir program çalışırken istisnalar meydana gelebilir ve dış kaynak serbest bırakılmaz."

"Ve bu çok kötü. Ne yapmalı?"

"Yöntemin her zaman çağrıldığından emin olmak için , kodumuzu bir - - close()bloğa sarmalı ve yöntemi bloğa eklemeliyiz . Şunun gibi görünecektir:trycatchfinallyclose()finally

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

"Hmm... Burada bir sorun mu var?"

"Doğru. Bu kod derlenmeyecek çünkü outputdeğişken bloğun içinde bildirildi try{}ve bu nedenle blokta görünmüyor finally.

Düzeltelim:

FileOutputStream output = new FileOutputStream(path);

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

"Şimdi her şey yolunda mı?"

"Önemli değil ama nesneyi oluşturduğumuzda bir hata oluşursa çalışmaz FileOutputStreamve bu oldukça kolay olabilir.

Düzeltelim:

FileOutputStream output = null;

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

"Ve şimdi her şey çalışıyor mu?"

"Hala birkaç eleştiri var. Birincisi, nesneyi oluştururken bir hata oluşursa FileOutputStream, o zaman outputdeğişken null olacaktır. Bu olasılığı blokta hesaba katmak gerekir finally.

"İkincisi, close()yöntem her zaman blokta çağrılır finally, yani blokta gerekli değildir try. Son kod şöyle görünecektir:

FileOutputStream output = null;

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

"İhmal edilebilecek bloğu dikkate almasak bile catch, o zaman 3 satırımız 10 olur. Ama temelde dosyayı açtık ve 1 yazdık."

"Vay... İyi ki konuyu kapatmış. Nispeten anlaşılır, ama biraz can sıkıcı, değil mi?"

"Öyle. Bu yüzden Java'nın yaratıcıları biraz sözdizimsel şeker ekleyerek bize yardımcı oldular. Şimdi programın en önemli kısmına, daha doğrusu bu derse geçelim:

try-kaynaklarla-kaynaklarla

"Java'nın 7. versiyonundan itibaren yeni bir try-with-resources deyimi var.

"Metoda zorunlu çağrı ile sorunu çözmek için tam olarak oluşturuldu close()."

"Kulağa umut verici geliyor!"

"Genel durum oldukça basit görünüyor:

try (ClassName name = new ClassName())
{
   Code that works with the name variable
}

try "Yani bu, ifadenin başka bir varyasyonu mu ?"

"Evet. Anahtar kelimeden sonra parantez eklemeniz tryve ardından parantez içinde harici kaynaklara sahip nesneler oluşturmanız gerekir. Parantez içindeki her nesne için derleyici bir finallybölüm ve yönteme bir çağrı ekler close().

"Aşağıda iki eşdeğer örnek var:

uzun kod try-with-resources içeren 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);
}

"Harika! -with-resources kullanan kod tryçok daha kısa ve okunması daha kolay. Ve ne kadar az kodumuz olursa, yazım hatası veya başka bir hata yapma şansımız o kadar az olur."

"Beğenmenize sevindim. Bu arada -with-resources ifadesine blok catchekleyebiliriz . Ya da ihtiyacınız yoksa ekleyemezsiniz.finallytry

Aynı anda birkaç değişken

"Aynı anda birkaç dosyayı açmanız gerektiğinde bir durumla karşılaşabilirsiniz. Diyelim ki bir dosyayı kopyalıyorsunuz, yani iki nesneye ihtiyacınız var: verileri kopyaladığınız dosya ve verileri kopyaladığınız dosya .

"Bu durumda, try-with-resources ifadesi, içinde bir ancak birkaç nesne oluşturmanıza izin verir. Nesneleri oluşturan kodun noktalı virgülle ayrılması gerekir. İşte bu ifadenin genel görünümü:

try (ClassName name = new ClassName(); ClassName2 name2 = new ClassName2())
{
   Code that works with the name and name2 variables
}

Dosya kopyalama örneği:

Kısa kod uzun kod
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);
}
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();
}

"Pekala, burada ne söyleyebiliriz? try-kaynaklarla-harika bir şey!"

"Söyleyebileceğimiz şey, onu kullanmamız gerektiğidir."