1. Panlabas na mapagkukunan

Habang tumatakbo ang isang Java program, minsan ay nakikipag-ugnayan ito sa mga entity sa labas ng Java machine. Halimbawa, may mga file sa disk. Ang mga entidad na ito ay karaniwang tinatawag na panlabas na mapagkukunan. Ang mga panloob na mapagkukunan ay ang mga bagay na nilikha sa loob ng Java machine.

Karaniwan, ang pakikipag-ugnayan ay sumusunod sa pamamaraang ito:

Pahayag ng Try-with-resources

Mga mapagkukunan sa pagsubaybay

Ang operating system ay mahigpit na sinusubaybayan ang mga mapagkukunang magagamit, at kinokontrol din ang nakabahaging pag-access sa mga ito mula sa iba't ibang mga programa. Halimbawa, kung binago ng isang program ang isang file, hindi maaaring baguhin (o tanggalin) ng isa pang program ang file na iyon. Ang prinsipyong ito ay hindi limitado sa mga file, ngunit nagbibigay sila ng pinaka madaling maunawaan na halimbawa.

Ang operating system ay may mga function (API) na nagbibigay-daan sa isang programa na kumuha at/o maglabas ng mga mapagkukunan. Kung ang isang mapagkukunan ay abala, kung gayon ang programa lamang na nakakuha nito ang maaaring gumana dito. Kung ang isang mapagkukunan ay libre, kung gayon ang anumang programa ay maaaring makuha ito.

Isipin na ang iyong opisina ay nagbahagi ng mga tarong ng kape. Kung may kumuha ng mug, hindi na ito makukuha ng ibang tao. Ngunit kapag ang mug ay nagamit na, nahugasan, at naibalik sa kinalalagyan nito, maaari na itong kunin muli ng sinuman. Ang sitwasyon sa mga upuan sa bus o subway ay pareho. Kung ang isang upuan ay libre, maaari itong kunin ng sinuman. Kung ang isang upuan ay okupado, kung gayon ito ay kinokontrol ng taong kumuha nito.

Pagkuha ng mga panlabas na mapagkukunan .

Sa tuwing magsisimulang magtrabaho ang iyong Java program sa isang file sa disk, hihilingin ng Java machine ang operating system para sa eksklusibong pag-access dito. Kung ang mapagkukunan ay libre, kung gayon ang Java machine ay nakakakuha nito.

Ngunit pagkatapos mong gawin ang file, ang mapagkukunang ito (file) ay dapat ilabas, ibig sabihin, kailangan mong ipaalam sa operating system na hindi mo na ito kailangan. Kung hindi mo ito gagawin, ang mapagkukunan ay patuloy na hahawakan ng iyong programa.

Ang operating system ay nagpapanatili ng isang listahan ng mga mapagkukunan na inookupahan ng bawat tumatakbong programa. Kung lumampas ang iyong program sa nakatalagang limitasyon sa mapagkukunan, hindi ka na bibigyan ng operating system ng mga bagong mapagkukunan.

Ang mabuting balita ay kung magwawakas ang iyong programa, ang lahat ng mga mapagkukunan ay awtomatikong ilalabas (ang operating system mismo ang gumagawa nito).

Ang masamang balita ay kung nagsusulat ka ng isang server application (at maraming mga server application ang nakasulat sa Java), ang iyong server ay kailangang tumakbo nang mga araw, linggo, at buwan nang walang tigil. At kung magbubukas ka ng 100 mga file sa isang araw at hindi isasara ang mga ito, pagkatapos ay sa loob ng ilang linggo ang iyong aplikasyon ay maaabot ang limitasyon ng mapagkukunan at pag-crash nito. Iyan ay kulang sa mga buwan ng matatag na trabaho.


2. close()paraan

Ang mga klase na gumagamit ng mga panlabas na mapagkukunan ay may espesyal na paraan para ilabas ang mga ito: close().

Sa ibaba ay nagbibigay kami ng isang halimbawa ng isang programa na nagsusulat ng isang bagay sa isang file at pagkatapos ay isinasara ang file kapag ito ay tapos na, ibig sabihin, pinapalaya nito ang mga mapagkukunan ng operating system. Mukhang ganito:

Code Tandaan
String path = "c:\\projects\\log.txt";
FileOutputStream output = new FileOutputStream(path);
output.write(1);
output.close();
Ang landas sa file.
Kunin ang file object: kunin ang mapagkukunan.
Sumulat sa file
Isara ang file - bitawan ang mapagkukunan

Pagkatapos magtrabaho sa isang file (o iba pang panlabas na mapagkukunan), kailangan mong tawagan ang close()pamamaraan sa bagay na naka-link sa panlabas na mapagkukunan.

Mga pagbubukod

Parang simple lang ang lahat. Ngunit ang mga pagbubukod ay maaaring mangyari habang tumatakbo ang isang programa, at ang panlabas na mapagkukunan ay hindi ilalabas. At iyon ay napakasama.

Upang matiyak na ang close()pamamaraan ay palaging tinatawag, kailangan naming balutin ang aming code sa isang try- catch- finallyblock at idagdag ang close()paraan sa finallyblock. Magiging ganito ang hitsura nito:

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

Ang code na ito ay hindi mag-compile, dahil ang outputvariable ay idineklara sa loob ng try {}block, at samakatuwid ay hindi makikita sa finallyblock.

Ayusin natin ito:

FileOutputStream output = new FileOutputStream(path);

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

Okay lang, ngunit hindi ito gagana kung may naganap na error kapag ginawa namin ang FileOutputStreambagay, at ito ay maaaring mangyari nang madali.

Ayusin natin ito:

FileOutputStream output = null;

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

Mayroon pa ring ilang mga kritisismo. Una, kung may naganap na error sa paggawa ng FileOutputStreamobject, outputmagiging null ang variable. Ang posibilidad na ito ay dapat isaalang-alang sa finallyblock.

Pangalawa, ang close()pamamaraan ay palaging tinatawag sa finallybloke, na nangangahulugang hindi ito kinakailangan sa trybloke. Ang huling code ay magiging ganito:

FileOutputStream output = null;

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

Kahit na hindi namin isaalang-alang ang catchbloke, na maaaring alisin, pagkatapos ang aming 3 linya ng code ay naging 10. Ngunit karaniwang binuksan lang namin ang file at nagsulat ng 1. Medyo mahirap, hindi ba?


3. try-may-resources

At dito nagpasya ang mga tagalikha ng Java na magwiwisik ng ilang syntactic na asukal sa amin. Simula sa ika-7 bersyon nito, may bagong try-with-resources na pahayag ang Java.

Ito ay nilikha nang tumpak upang malutas ang problema sa ipinag-uutos na tawag sa close()pamamaraan. Ang pangkalahatang kaso ay mukhang medyo simple:

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

Ito ay isa pang pagkakaiba-iba ng try pahayag . Kailangan mong magdagdag ng mga panaklong pagkatapos ng trykeyword, at pagkatapos ay lumikha ng mga bagay na may mga panlabas na mapagkukunan sa loob ng mga panaklong. Para sa bawat bagay sa mga panaklong, ang compiler ay nagdaragdag ng isang finallyseksyon at isang tawag sa close()pamamaraan.

Nasa ibaba ang dalawang katumbas na halimbawa:

Mahabang code Code na may try-with-resources
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);
}

Ang code na gumagamit ng try-with-resources ay mas maikli at mas madaling basahin. At mas kaunti ang code na mayroon tayo, mas maliit ang pagkakataong gumawa ng typo o iba pang error.

Sa pamamagitan ng paraan, maaari tayong magdagdag catchat finallymag-block sa try-with-resources na pahayag. O hindi mo maaaring idagdag ang mga ito kung hindi sila kailangan.



4. Ilang mga variable sa parehong oras

Sa pamamagitan ng paraan, maaari kang madalas na makatagpo ng isang sitwasyon kung kailan kailangan mong magbukas ng ilang mga file sa parehong oras. Sabihin nating kumukopya ka ng isang file, kaya kailangan mo ng dalawang bagay: ang file kung saan mo kinokopya ang data at ang file kung saan ka kumukopya ng data.

Sa kasong ito, tryhinahayaan ka ng -with-resources na pahayag na lumikha ng isa ngunit ilang mga bagay dito. Ang code na lumilikha ng mga bagay ay dapat na pinaghihiwalay ng mga semicolon. Narito ang pangkalahatang hitsura ng pahayag na ito:

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

Halimbawa ng pagkopya ng mga file:

Mahabang code Maikling code
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);
}

Well, ano ang masasabi natin dito? try-with-resources ay isang kahanga-hangang bagay!


5. AutoCloseableinterface

Ngunit hindi lang iyon. Ang matulungin na mambabasa ay agad na magsisimulang maghanap ng mga pitfalls na naglilimita kung paano mailalapat ang pahayag na ito.

Ngunit paano trygumagana ang -with-resources statement kung walang close()pamamaraan ang klase? Kumbaga, walang tatawagin. Walang paraan, walang problema.

Ngunit paano trygumagana ang -with-resources statement kung ang klase ay may ilang close()pamamaraan? At kailangan nila ng mga argumento na maipasa sa kanila? At ang klase ay walang close()pamamaraan na walang mga parameter?

Sana talaga tinanong mo ang iyong sarili sa mga tanong na ito, at marahil sa iba pa.

Upang maiwasan ang mga ganitong isyu, gumawa ang mga tagalikha ng Java ng isang espesyal na interface na tinatawag na AutoCloseable, na mayroon lamang isang paraan — close(), na walang mga parameter.

Idinagdag din nila ang paghihigpit na ang mga bagay lamang ng mga klase na nagpapatupadAutoCloseable ang maaaring ideklara bilang mga mapagkukunan sa isang try-with-resources na pahayag. Bilang resulta, ang mga naturang bagay ay palaging magkakaroon ng close()paraan na walang mga parameter.

Sa pamamagitan ng paraan, sa tingin mo ba posible para sa isang try-with-resources na pahayag na ideklara bilang isang mapagkukunan ang isang bagay na ang klase ay may sariling close()pamamaraan na walang mga parameter ngunit hindi nagpapatupad AutoCloseable?

Ang masamang balita: Ang tamang sagot ay hindi — dapat ipatupad ng mga klase ang AutoCloseableinterface.

Ang magandang balita: Ang Java ay may maraming mga klase na nagpapatupad ng interface na ito, kaya malamang na ang lahat ay gagana ayon sa nararapat.