Wednesday, 1 March 2017

განსაკუთრებული ღონისძიებები(Exceptions)

                     


გამონაკლისები არის ღონისძიებების ერთობა რომელიც ახდენს ნოტოფიცირებას მოვლენის, რომელმაც ხელი შეუშალა კოდის ნორმალურ ფუნქციონირებას.  როდესაც მეთოდში ჩდება ერორი ის ქმნის ობიეკტს, რომელსაც აწვდის სისტემას, ობიეკტი რომლის მიწოდებაც ხდება სისტემაზე გახლავთ Exception Object და ის შეიცავს ინფორმაციას ერორზე, მის გამომწვევ მიზეზებზე, ადგილ-მდებარეობაზე, ტიპზე, ველზე(თუ რომელ ველზე მოხდა ერორის გამოწვევა) და სხვა დეტალურ მონაცემებს რომელიც შემდგომში გეხმარებათ ერორზე გამკლავებაში.  Exception Object-ის შექმნის და სისტემაზე გადაწოდების პროცეს ქვია trowing an exception. ნებისმიერი მეთოდი ახდენს ერორ მესიჯის გაადსროლას (მიწოდებას) სისტემაზე, საკვანძო სიტყვა throw-throws გამოყენებით. ის სიგნალირების ფუნქციას ასრულებს, რომელიც აფრთხილებს სისტემას მოსალოდნელი ერორის (არა ნორმალური სიტუაციის) შესახებ.  როდესაც კოდი იწვევს გამონაკლის პროგრამის ფაკტობრივი სტატუსი ჩერდება(წყვეტს მუშაობას) მანამ სანამ არ მონახავს სიტუაციიდან გამოსავალს. ანუ იწყებს კოდის ძებნას რომელიც გაუმკლავდება პრობლემას და ამ კოდს Exception handler ქვია. გამონაკლისი პროგრამისტს აძლევს საშუალებას მოახდინოს დამუშავება საფრთხის შემცველი კოდის, განსხვავებულ სიტუაციებში მოახდინოს განსხვავებული რეაგირება პრობლემაზე, კოდი გახადოს უფრო წაკითხვადი, სუფთა და ეფეკტური.
გამონაკლისი ჯავაში არის ძლიერი იერარქიული ხელსაწყო, რომლის მეშვეობითაც ხდება ცენტრალიზება პრობლემების. რეკომენდირებულია გამონაკლისების მეშვეობით მოახდინოთ პრობლემების მართვა, ერორების და მათი ქცევის წესების, რომელიც თავს იჩენს ხოლმე კოდში.

გამონაკლისების პლიუსი ობიეკტზე ორიენტირებულ პროგრამირებაში არის ის რომ ისინი იერარქიულად არიან განლაგებული, ანუ იყენებენ მემკვიდრეობას, ყველა გამონაკლისი არის კლასი, რომელიც მემკვიდრეა მეორე კლასის და ა.შ გამომდინარე აქედან გამონაკლისებს აქვს საბაზისო კლასები და ქვე კლასები რაც საშუალებას გვაძლევს ერთი საბაზისო კლასის გამოყენებით „ერთი ხელის მოძრაობით“ მოვაგვაროთ პრობლემათა ერთობა. განსხვავებით სტრუკტურული პროგრამირებისა სადაც ყველა პრობლემის ინდივიდუალურად მოგვარება უწევს პროგრამისტს.
გამონაკლისი გახლავთ ობიეკტი, რომელიც მემკვიდრეა საბაზისო კლას throwable-ის. ის სუპერ კლასია ყველა გამონაკლისი კლასის და შეიცავს შემდეგ ინფორმაციას.

  •   getMessage(); - გვიბრუნებს მესიჯს ერორთან დაკავშირებით
  •  getStackTrace(); - გვიბრუნებს მთლიან ინფორმაციას ერორთან დაკავშირებით
  • getCause(); - გვიბრუნებს ერორის გამომწვევ მიზეზებს.

ჯავაში (და არა მარტო ჯავაში)  არსებობს მთლიანი იერარქია პრობლემებთან გამკლავებისთვის, თქვენ როგორც პროგრამისტს კოდის წერა თითქმის არ მოგიწევთ, უბრალოდ სასწავლი გექნებათ ამ კლასების ერთობა, რომელი რომლის მემკვიდრეა, რომელს რა ფუნქცია გააჩნია რათა მოახდინოთ მათი ეფეკტურად გამოყენება. (ყველაფერი თქმული არ ნიშნავს იმას რომ თქვენ თვითონვე არ შეგიძლიათ კლასის შექმნა, რომელიც დაგეხმარებათ პრობლემების მოგვარებაში, უბრალოდ უნდა შექმნათ კლასი რომელიც extends Exception, რის შემდგომაც საკუთარ ლოგიკას ჩამოაყალიბებთ, მაგალითს გაჩვენებთ. ) ნახეთ იერარქია.

ძირითადი კლასები იერარქიაში არის:


  • Throwable(super Class).
  • Error - საბაზისო კლასი რომელიც შეიცავს ინფორმაციას სისტემურ ერორებზე.  პროგრამისტს ერორ კლასიდან გამოწვეულ ერორებზე გამკლავება არ უხდება, 
  • RunTimeException - საბაზისო კლასი რომელიც შეიცავს პროგრამის მიერ გამოწვეულ ერორებს.
  • Exception -  საბაზისო კლასი ყველა დანარჩენი “Exception“ კლასების რომლებზეც გამკლავება მოგიწევთ.

გამონაკლისები კლასების გარდა დაყოფილია ტიპებად, შემოწმებული, შეუმოწმებელი და ერორები:

Checked Exceptions- გახლავთ გამონაკლისები რომელიც გადამოწმებულია ავტომატურად კომპილატორის მიერ. ყველა ქვე კლასი(გარდა RunTimeException-სა) Exception კლასისა გახლავთ შემოწმებული გამონაკლისი, ანუ მასზე გამკლავება პროგრამისტის მოვალეობა გახლავთ, წინააღმდეგ შემთხვევაში პროგრამა შეწყვიტავს მუშაობას. ყველაზე ხშირად გამოყენებაში გვხვდება ClassNotFoundException, NotSuchMethodException ან IOException

Unchecked Exceptions - თავს იჩენს პროგრამული შეცდომის ან ვირტუალურ მანქანაში პრობლემების ქონის დროს,  ყველა ობიეკტი რომელიც მემკვიდრეა RunTimeException კლასის გახლავთ შეუმოწმებელი გაონაკლისები. მათზე კოდურ დონეზე გამკლავება არ არის კარგი პრაკტიკა. ყველაზე ხშირად გამოყენებაში გვხვდება NullPointerException და ArrayIndexOutOfBoundsException, როგორც წესი პროგრამისტი მსგავს ერორამდე არ მიდის და თუ მიდის ეს ელემენტალური შეცდომის ბრალია ხოლმე, ამიტომ ითვლება მათზე გამკლავება ცუდ პრაკტიკად, (უბრალოდ არ უნდა დაუშვათ შეცდომა რომელიც მსგავს პრობლემას გამოიწვევს) მაგრამ იშვიათად არის სიტუაციები როდესაც გიწევთ მათზე გამკლავება, ძირითადად მაშინ როცა მომხმარებლისგან ცდილობთ ინფორმაციის მიღებას. 

Error- შეუმოწმებელი გამონაკლისი. კრიტიკული სიტუაციები, ფატალური ერორები, რომლის გამოც პროგრამა იძულებული ხდება შეწყვიტოს მუშაობა, მსგავსი პრობლემის გათვალისწინებას კოდის წერის დროს ვერ მოახერხებთ, ამიტომ არის შეუმოწმებელი გამონაკლისი, მაგალითად შუქი ჩაქრა, კოდმა შეწყვიტა ფუნქციონირება, მეხსიერება გადაივსო, სტაკი ან ჰიპი არ აქვს მნიშვნელობა, კოდის დონეზე ამას ვერ აუვლით გვერდს, უფრო ტექნიკური ჩარევა ჭირდება. ყველა კლასი რომელიც მემკვიდრეა ერორ კლასის გახლავთ შეუმოწმებელი გამონაკლისი.

შემოწმებული გამონაკლისები არის გამონაკლისები რომელიც მუშაობს პრინციპით „დაიჭირე და გადაისროლე“ (catch and throw), რომლის გარანტადაც გვევლინება კომპილატორი, შემოწმებული გამონაკლისები მემკვიდრეა კლასის java.lang.Exceptions. მაგრამ არ არის მემკვიდრე java.lang.RunTimeExceptions, ამის ცოდნა მნიშვნელოვანია რადგან შეუმოწმებელი გამონაკლისი თვითონ მემკვიდრეა გამონაკლისის, ხშირად დამწყებ პროგრამისტებში ეს გაურკვევლობას იწვევს, დახედეთ კიდევ ერთხელ იერარქიის ფოტოს. ნებისმიერი წესიერად დაწერილი კოდი მუდმივად მოლოდინის რეჟიმში უნდა იყოს რათა გაუმკლავდეს დაშვებულ გამონაკლის და მოახდინოს ფუნქიონალიზმის აღდგენა მისი გამოწვევის შემდეგ.

შემოწმბული გამონაკლისი რომელიც ხშირად გვხვდება:
ClassNotFoundException
IOException
EOFException
FileNotFoundException
NoSuchMethodException

შეუმოწმებელი გამონაკლისი რომელიც ხშირად გვხვდება:
ArithmeticException
IllegalArgumentException
NumberFormatException
IndexOutOfBoundsException
ArrayIndexOutOfBoundsException
StringIndexOutOfBoundsException
NullPointerException

                                          როგორ მუშაობს გამონაკლისი.
როდესაც კოდის ნორმალური ფუნქციონირების დროს რომელიმე მეთოდი იწვევს გამონაკლის და ისვრის ერორ ობიეკტს, პროგრამა წყვეტს მუშაობას და იძლევა ნოტიფიკაციას არსებული პრობლემის შესახებ,  ფუნქიონირების აღდგენა არ ხდება მანამ სანამ ვირტუალური მანქანა არ მონახავს კოდს პროგრამაში რომელიც გაუმკლავდება პრობლემას, ნოთიფიკაცია თქვენ, პროგრამისტს გაძლევთ საშუალებას მონახოთ საფრთხის მატარებელი მეთოდი და დაამუშაოთ ის (აკონტროლოთ მისი ქცევის წესები).  პრობლემის გამოწვევის დროს ვირტუალური მანქანა იწყებს კოდის ძიებას სტაკ მეხსიერებაში, ამ პროცეს call stack ქვია, თუ გახსოვთ როგორ ხდება სტაკ მეხსიერებაში ინფორმაციის შესვლა და გამოსვლა ,მარტივად გაერკვევით მოქმედების პრინციპშიც. სტაკ მეხსიერება მუშაობს LIFO(Last In First Out) პრინციპით, გამომდინარე აქედან მეხსიერებაში პირველი შედის მთავარი მეთოდი დ ის ექცევა მეხსიერების ძირში. შემდგეგ მოყვება ყველა დანარჩენი მეთოდი თანმიმდევრეულად, თუ პრობლემა გამოიწვია მეათე მეთოდმა ვირტუალური მანქანა იწყებს კოდის ძებნას მეათე მეთოდიდან დაბლა, თანმიმდევრულად კითხულობს ყველა მეთოდს, თუ მიაგნო კოდს რომელიც დაეხმარება პრობლემის მოგვარებაში ის მას დაამუშავებს და გამოიყენებს, თუ ვერ მიაგნო მიდის მთავარ მეთოდამდე და ისვრის Exception Object-ს.  ერთი ფოტო სურათი უამრავ სიტყვას უდრის:


დაუშვათ ძიების დროს თუ მოხდა ისე რომ რომელიმე მეთოდი გავიდა სტაკიდან, მაგალითად დაასრულა მუშაობა და return საკვანძო სიტყვით დატოვა მეხსიერება, ძიება ამ შემთხვევაში გრძელდება შემდეგ მეთოდზე, 10,9, 8(return ) გამოტოვა, 7 და ა.შ. ყველაფერი ნათელია. ვიცით როგორ ხდება ძიება კოდის, დროა გავიგოთ როგორ ხდება მისი დამუშავება.

ჯავაში 5 საკვანძო სიტყვა არის გამოყოფილი რათა დავამუშაოთ გამონაკლისი, ესენია try,catch, finally, throw, throws.

Throw - ახდენს სიგნალიზირებას  და გადასროლას ერთი პრობლემის Explicity.

Throws – ახდენს დეფინირებას მეთოდის დასათაურების გასწვრივ პრობლემებისა, რომელიც შეიძლება გამოიწვიოს კონკრეტულმა მეთოდმა, გადაისვრის მონიშნულ გამონაკლის ან გამონაკლისების ერთობას, ხშირ შემთხვევაში თვითონ უმკლავდება ან პრობლემას აწვდის ქვემდგომ მეთოდს სტაკ მეხსიერებაში.

Try-გადასროლილი პრობლემის ან პრობლემების მოქცევა ხდება Try ბლოკში, შესაძლებელია ერთი Try ბლოკის ქონა, თუ სურვილი გაქვთ იქონიოთ მრავალი და იერარქიულად პრობლემა გადააწოთ სულ უფრო მაღლა შეგიძლიათ მოახდინოთ მისი ჩაბუდება. Try ბლოკს ერთი Catch ან ერთი Finally ბლოკი აუცილებლად უნდა ექნეს.

Catch - შესაძლებელია ერთი Try ბლოკის შემდგომ იქონიოთ იმდენი Catch ბლოკი რამდენის სურვილიც გაქვთ, 1 დაიჭერს ერთ პრობლემას, მეორე მეორეს და ასე შემდეგ, ყველა პრობლემაზე გამკლავება შეიძლება ერთდროულად თუ ეს პრობლემები მოქცვეულია Try ბლოკში.

Finally- ბლოკი არის ბლოკი რომლის ეგზეკუციაც ხდება ნებისმიერ სიტუაციაში, რაც არ უნდა მოხდეს ის ახდენს კომპილირებას, მაშინაც კი თუ რომელიმე ზემოთ ხსენებული ველი დაასრულებს ფუნქციონალიზმს და გავა მეხსიერებიდან return-ის მეშვებოით. როგორც ვისწავლეთ return-ის მერე არ ხდება არც ერთი ველის წაკითხვა, ეს წესი Finally ბლოკს არ ეხება, ის მაინც იკითხება.(ფინალური ბლოკის წაკითხვა არ ხდება მხოლოდ ერთ სიტუაციაში, როდესაც ვირტუალური მანქანა წყვეტს მუშაობას გარკვეული ან გაურკვეველი მიზეზების გამო. მაგ: System.exit() მეთოდი თიშავს ვირტუალურ მანქანას.) შესაძლებელია ერთი Finally ბლოკის ქონა ერთ Try ბლოკთან.

თუ პრბლემის გადასროლა ხდება Try ბლოკიდან მის ქვემოთ მდგომი Catch ბლოკი წყვეტს მუშაობას მანამ სანამ არ მოხდება გადასროლილ პრობლემაზე გამკლავება, ანალოგიურად Catch ბლოკებშიც თუ ხდება პრობლემის გადასროლა ქვე-მდგომი ფუნქციონალიზმი  წყვეტს მუშაობას, რადგან throw საკვანძო სიტყვა გარდა იმისა რო Explicity ისვრის პრობლემას ახდენს მის ქვემოთ მდგომი ოპერაციების გაჩერებას, ანუ რაღაცით Return, Break, Continue საკვანძო სიტყვებს წააგავს, try/catch კი  if/ else statement-ს გავს. (პრობლემა თქვენ მიერ იქნება გადასროლილი თუ კომპილატორის მიერ არ აქვს მნიშვნელობა, გადასროლილი ველის შემდგომ წაკითხვა არ ხდება, სანამ არ მოხდება პრობლემაზე გამკლავება)

სურათზე ხედავთ განსხვავებულ ერორ მესიჯებს, 1. არის stacktrace მესიჯი, რომელიც შეიცავს მთლიან ინფორმაციას ერორზე. პაკეტის დასახელებას, კლასის დასახელებას, და კონსტუკტორის შიგთავს, როდესაც ვწერთ getStrackTrace მეთოდს მსგავსი მესიჯი გამოდის კონზოლში. 2. ერორ მესიჯი გახლავთ სტანდარტული ერორი რომელიც გამოიწვია მეთოდმა, რომლის დასახელებაც არის open0(); 3. ერორი გახლავთ ობიეკტური მეთოდის ერორი, რომლის დასახელებაც არის open და არის File-ის ტიპის, შეცდომა ხელმისაწვდომია 195 ველზე. 4. როდესაც დასახელების ნაცვლად კონზოლში ვხედავთ <init> -ს კლასის დასახელების შემდგომ ეს იმას ნიშნავს რო პრობლემა კონსტუკტორშია. ამ კონკრეტულ სიტუაციაში კონსტუკტორში რომელიც იმყოფება 138 ველზე.
ასე თუ ისე სტანდარტული წარმოდგენა შეგვექმნა როგორ მუშაობს გამონაკლისი, დროა დეტალურად განვიხილოთ მისი დადებითი და უარყოფითი მხარეები. ვნახოთ გამოყენების წესები და მაგალითები.
               
                                                     Java Exception Handling
                 
ჯავაში გამონაკლისზე გამკლავება არის ერთ-ერთი ყველაზე მნიშვნელოვანი თავი, თუ გსურთ რო დაწეროთ საიმედო და ძლიერი კოდი უნდა გაითვალისწინოთ ყველა მოსალოდნელი საფრთხე რომელსაც თქვენი კოდი შეხვდება მუშაობის დროს, ამას რომ მიაღწიოთ კარგად უნდა ერკვეოდეთ პრობლემის გადასროლაში, დაჭერაში და დამუშავებაში, როგორ ახდენთ გადასროლას, დაჭერას და დამუშავებას ამასაც ძალიან დიდი მნიშვნელობა აქვს, არსებობს რამოდენიმე განსხვავებული გზა რათა მოახდინოთ კოდის დამუშავება, რა თქმა უნდა ყველა ერთნაირად ეფეკტური და უსაფრთხო არ არის და სწორედ ამას განვიხილავთ ამ თავში. არ ვიცი იცით თუ არა მაგრამ ჯავა იმ მცირე ენებს შორის არის რომელიც მხარს უჭერს შემოწმებული და შეუმოწმებელი გამონაკლისების ერთდროულად ქონას, რის გამოც ხშირად კრიტიკის ქარცეცხლში უწევს გავლა. ამ თავში ვისაუბრებ შემოწმებული და შეუმოწმებელი გამონაკლისების პლიუსებზე და მინუსებზე.

Throws მაგალითები:

როდესაც ვქმნით მეთოდს რომელიც ციფრების გაყოფაზე მუშაობს, სავარაუდოა რო ნულზე გაყოფა შეიძლება მოხდეს, ნულზე გაყოფა არ არის დაშვებული, გამომდინარე აქედან გვიწევს ამ პრობლემაზე გამკლავება, სურათზე ხედავთ, როგორ ისვრის მეთოდი DoNotDivideByZero გამონაკლის, მსგავსი გამონაკლისი არ არსებობს იერარქიაში, ჩემი შექმნილია და როგორ უნდა შექმნათ თქვენ, თქვენი მოგვიანებით განახებთ. ამ მეთოდში კი გადასროლის მერე არ ხდება მასზე განკლავება, ანუ მეთოდი უბრალოდ ახდენს ნოტიფიცირებას სისტემის რო ეს მეთოდი გამოიწვევს პრობლემას, რომელსაც სადმე უნდა გაუმკლავდეთ, წითლად ხასგასმულ ველზე ხედავთ რო პრობლემა ხელოვნურად არის გადასროლირი, თუ რომელიმე შეყვანილი ციფრი უდრის 0-ს მაშინ ეკრანზე უნდა გამოვიდეს ინფორმაცია რო ნულზე გაყოფა არ შეიძლება, როგორც მაღლა ავღნიშნე, throw ველის მერე ინფორმაციის წაკითხვა არ ხდება მანამ სანამ პრობლემას არ მივხედავთ სადმე. შესაბამისად გაყოფა რომელიც return ველზე ხდება არასდროს არ შესრულდება თუ მომხმარებელი ნულს შეიყვანს. თქვენ შეგიძლიათ ნებისმიერი რაოდენობის და ტიპის გამონაკლისი გადაისროლოთ მეთოდიდან, ისევე როგორც შეგიძლიათ შექმნათ კონკრეტული სახის გამონაკლისი რომელიც კონკრეტული კლასის მემკვიდრეა და არა მთლიანად გამონაკლისი კლასის, ჩემი გამონაკლისი ამ მაგალითზე მემკვიდრეა Exception გამონაკლისის.

Try/catch მაგალითი:
თუ მეთოდი იძახებს მეთოდს რომელიც ისვრის გამონაკლსის ის იძულებული ხდება გაუმკლავდეს გამონაკლის ან თვითონ მოახდინოს მისი გადასროლა.

მეორე მეთოდში გამოვიძახეთ მეთოდი რომელიც გაუმკლავდება პრობლემას , გადასროლილს ზემდგომი მეთოდიდან, ფოტოზე ხედავთ თუ როგორ ექცევა პრობლემური კოდი try  ბლოკში და catch როგორ ახდენს მის დამუშავებას. ეს არის ძირითადი მოვალეობა გამონაკლისების, რომ მომხმარებელს აცნობოს შეცდომის შესახებ. გამოვიძახოთ მეორე მეთოდი ძირითად მეთოდში და ვნახოთ კონზოლის შიგთავსი.

კომპილირების შემდგომ:

პროგრამა აგრძელებს მუშაობას.
რა მოხდებოდა რომ პრობლემაზე არ მიგვეხედა, ან ნაწილობრივ მიგვეხედა.

ანუ გავითვალისწინეთ რო ერთი ციფრი არ უნდა იყოს ნული, მაგრამ მეორე დაგვავიწყდა. შედეგად მივიღებდით:

გაჩერებულ პროგრამას მსგავსი შინაარსის მესიჯით. ArithmeticException არის UnChecked Exception. ანუ კომპილატორი არსად მიგვანიშნებს იმაზე რო შეცდომას ვუშვებთ, მაგიტომაც შევქმენი საკუთარი Checked გამონაკლისი, რომელსაც გამოვიყენებ ყოველთვის თუ სადმე ნულზე გაყოფასთან მომიხდა მუშაობა. შემდეგ მაგალითზე ვნახოთ თუ როგორ ხდება გამონაკლისის გადასროლა try/catch ველებიდან.
მთავარი წესი რომელიც უნდა გვახსოვდეს try/catch ველიდან გადასროლის დროს არის ის რომ არ ხდება ინფორმაციის წაკითხვა ხელოვნურად გადასროლის შემდგომ სხვა ველების რომელიც გადასროლილი ობიეკტის დაბლა დგას,  აგრეთვე ხდება იგნორირება არსებული გამონაკლისის რომელიც გადაისროლა try/catch ველებმა, და პრიორიტეტული ხდება გადასროლა რომელიც Explicity გადავისროლეთ. შესაძლებელია Explicity გადასროლის დროს გადასროლილმა ობიეკტმა მთლიანად შეითავსოს აქტიური პრობლემა, ანუ მოაქციოს ის მისი გავლენის ქვეშ, შესაბამისად ვიღებთ გამონაკლის რომელიც უმკლავდება გამონაკლის და პრობლემას ერთდროულად. ხშრირად შეხვდებით მსგავს ოპერაციებს, Explicity გადასროლის გამოყენების სურვილი იმიტომ ჩდება რო პროგრამისტს სურვილი უჩდება მიხედოს პრობლემას რომელსაც სავარაუდოდ მისი კოდი გამოიწვევს, არც ვირტუალურმა მანქანამ და არც კომპილატორმა ამის შესახებ არაფერი იციან იმიტომ რო კოდი რომელიც უნდა დაიწეროს და რომელზეც გამკლავება უნდა მოხდეს პროგრამისტის თავშია, ანუ არ არის ჯერ შექმნილი, გამომდინარე აქედან კოდის წერის დროს იწყება ხელოვნური გადასროლები რომელსაც შემდგომ, რომელიმე მეთოდში ან მანდვე უმკლავდება პროგრამისტი. აგრეთვე იდეალურია მომხმარებლამდე კონკრეტული მესიჯის მიტანისთვის. გამოსადეგია როდესაც ვიცით რომელი ველი გადაისვრის ერორს და მოვახდენთ ამ ველის გადასროლას რადგან ამით ნოტიფიკაციას ვიძლევით რომ ეს ველი პრობლემურია, შემდგომ კი კომპილატორი მასზე გამკლავებას გვაიძულებს „სადმე“.
მაგალითი 1: throw



მოცემულ ფოტოზე ნაჩვენებია როგორ ხდება წაკითხვა კოდის როდესაც ვიყენებთ throw საკვანძო სიტყვას. შავ ჩარჩოებში ნათელია რაც ხდება, ისვრის პრობლემას და მანდვე უმკლავდება, წითელ ჩარჩოებში კი გამკლავება ხდება სხვა მეთოდში, ამიტომაც გადასროლის შემდგომ წყდება ყველა სახის ოპერაცია და იწყება ძებნა სტაკ მეხსიერებაში, მე-2 ჩარჩოში აგნებს ვირტუალური მანქანა კოდს რომელიც პრობლემას მოაგვარებს და უბრუნდება საწყის მდგომარეობას, ანუ ასრულებს იმ მეთოდის კითხვას საიდანაც მოხდა გადასროლა, ბრუნდება მეთოდში სადაც მოხდა გამკლავდება და ასრულებს მის წაკითხვას. პროგრამა ფოტოზე მარტივია, სახელი და ასაკის შეყვანას ითხოვს მომხმარებლისგან, ორივე გამონაკლისი არის შეუმოწმებელი გამონაკლისი, რადგან შეუმოწმებელი და შემოწმებული გამონაკლისების შიგთავსი იდენტურია მაგალითად გამოდგება.

ძირითადი მეთოდი. და შემდგომ კომპილირება:

მაგალითი 2:
 Implicitly-Explicitly გადასროლის შემდგომ არ ხდება ველების წაკითხვა.

კომპილატორი ვერ ხედავს სისაუთ მეთოდს რადგან ვირტუალურმა მანქანამ ძიება დაიწყო სტაკ მეხსირებაში, მისი ყურადღება მიპყრობილი აქვს ნებისმიერ მეთოდს იერარქიულად დაბლა გარდა ინფორმაციისა რომელიც გადასროლის შემდგომ არის დაწერილი.

მაგალითი 3:
დაუშვათ დაიჭირეთ გამონაკლისი და მანდვე ქეჩ ბლოკიდან მოახდინეთ სხვა ტიპის გამონაკლისის გადასროლა, მაშინ ტიპი რომლის გადასროლასაც ახდენთ შესაძლებელია აქციოთ დაჭერილი პრობლემის მატარებლად. 


ფოტოზე ისრებით ნაჩვენებ ადგილებს დააკვირდით, როცა ქეჩ ბლოკიდან ვახდენთ გადასროლას, მაშინ ხშირ შემთხვევაში აუცილებელია რო მეთოდის გასწვრივ მოვახდინოთ დეფინირება იმ კლასის რომელსაც ვისვრით, (თუ გადასროლა ხდება try ბლოკიდან მაშინ ამის აუცილებლობა არ არსებობს, თუმცა შესაძლებელია) რადგან ამით კკომპილატორს ვაცნობებთ რო მეთოდი ერორის მატარებელია და მასზე აუცილებელია გამკლავება, ჩვენ სიტუაციაში კი, ვუმკლავდებით ფაილ გამონაკლის, IOException არის სუპერ კლასი ყველა ფაილ გამონაკლისების, შემდგომ ვახდენთ ახალი ერორ მესიჯის გადასროლას რომელიც შეიცავს ფაილის შიგთავს. ჩვენ მიერ შექმნილი გამონაკლისი ხდება მატარებელი სტანდარტული გამონაკლისის. როდესაც გაუმკლავდებით ჩვენ გამონაკლის გავუმკლავდებით სტანდარტულ გამონაკლისაც.

კომპილირების შემდგომ კარგად ჩანს რო ერთი printStackTrace მეთოდით ინფორმაციას ვიღებთ ორივე გამონაკლისზე.

მაგალითი 3: throw from finally block

არასდროს არ ცადოთ პრობლემის გადასროლა finally ბლოკიდან, ამის აუცილებლობას თითქმის არ შეხვდებით, ბევრი პროგრამისტი, მათ შორის დიდი გამოცდილების მქონე პროგრამისტებიც ხშირად ისვრის ხოლმე პრობლემას finally ბლოკიდან, ჩემი რჩევა იქნება რომ ეს არ გააკეთოთ შემდეგი მიზეზების გამო:
1.      თუ try ბლოკმა წარმატებით დაასრულა ოპერაცია, იწყება ფინალური ბლოკის ეგზეკუცია, ფინალური ბლოკის ეგზეკუციის დროს თუ ფინალურმა ბლოკმა წარმატებით დაასრულა ოპერაცია მაშინ try ბლოკიც წარმატებით დასრულდება, მაგრამ თუ try ბლოკმა წარმატებით დაასრულა ოპერაცია და ფინალურმა ბლოკმა პრობლემას ვერ გაართვა თავი, მაშინ try  ბლოკიც ვერ ართმევს ოპერაციას თავს ზუსტად იმ მიზეზით რა მიზეზითაც ვერ გაართვა ოპერაციას თავი ფინალურმა ბლოკმა.
2.     თუ try ბლოკი წარმატებით ასრულებს ოპერაციას, მისი დამუშავების ძიება იწყება catch ბლოკში, თუ მოინახა კლასი catch ბლოკში რომელიც დაამუშავებს გადმოსროლილ ინფორმაცია იწყება ფინალური ბლოკის ეგზეკუცია. თუ ფინალური ბლოკიც წარმატებით დამუშავდა მაშინ მთლიანი ოპერაცია წარმატებით დასრულდება, მაგრამ თუ ფინალურმა ბლოკმა ვერ მოახერხა ოპერაციაზე თავის გართმევა   try და catch ველებზე შესრულებული ოპერაციები ზუსტად იგივე მიზეზით ვერ შესრულდება რა მიზეზითაც ვერ მოახერხა ოპერაციაზე თავის გართმევა ფინალურმა ბლოკმა,
3.     თუ catch ბლოკმა “x” მიზეზის გამო ვერ გაართვა ოპერაციას თავი, იწყება ფინალური ბლოკის ეგზეკუცია, ფინალური ბლოკის წარმატებით დასრულების შემთხვევაში try ბლოკი ვერ ასრულებს ოპერაციას catch ბლოკის მიერ გამოწვეული “x” მიზეზის გამო. ანუ ხდება მხოლოდ ფინალური ბლოკის ეგზეკუცია, მაგრამ თუ ფინალურმა ბლოკმა ვერ გაართვა ოპერაციას თავი „Y“ მიზეზის გამო, მაშინ try ბლოკიც ვერ ართმევს თავს ოპერაციას „Y“ მიზეზის გამო, რაც იწვევს “x” მიზეზის მთლიანად დაგარკვას.
4.     თუ try ბლოკიდან გადასროლილ “x”  გამონაკლის ვერ უმკლავდება ვერც ერთი კლასი catch მეთოდ-ში, მაშინ იწყება ფინალური ბლოკის ეგზეკუცია, თუ ფინალური ბლოკის ოპერაცია დასრულდა წარმატებით მაშინ try ბლოკის ოპერაცია ვერ სრუდლება დადებითი შედეგით(იმიტომ რო არ მოინახა კლასი რომელიც მას გაუმკლავდება), მაგრამ თუ ფინალური ბლოკი იწვევს „Y“ პრობლემას მაშინ “x”   პრობლემა ქრება, მას ვირტუალური მანქანა არასდროს მოუბრუნდება.
მგონი საკმარისი მიზეზია იმისათვის რო ფინალური ბლოკიდან არ მოახდინოთ პრობლემის გადასროლა, ზუსტად იგივე ან მიახლოებით იგივე პრობლემებს გამოიწვევთ თუ ფინალურ ბლოკში გექნებათ return, break, continue საკვანძო სიტყვები (ეს არ ნიშნავს იმას რომ ამის გაკეთება არ შეგიძლიათ). დაიამხსოვრეთ ფინალურ ბლოკს აქვს მხოლოდ ერთადერთი დანიშნულება, ამ ბლოკში ხდება რესურსების უსაფრთხოდ დაკეტვა. File,close(),Sql.close(), flash() და ა.შ. დაკეტვის დროს შეგიძლიათ ჩააბუდოთ try/catch ბლოკი ფინალურ ბლოკში, ეს არანაირ საფრთხეს არ შეიცავს, ჩააბუდებთ და მანდვე გაუმკლავდებით პრობლემას.  P.S და მაინც თუ აღმოჩდით გამოუვალ სიტუაციაში და მოგიწიათ ფინალური ბლოკიდან გამონაკლისის გადასროლა, სტაკ მეხსიერებაში ვირტუალური მანქანა მას წაიკითხავს და არა try/catch ბლოკიდან გადასროლილ გამონაკლის. არ არის ლოგიკური აშკარად, მაგრამ ასეა!  
მაგალითი:

გარდა try/cacth-სა ფინალურ ბლოკში შეგიძლიათ გამოიძახოთ მეთოდი სადაც ზუსტად იგივე ოპერაცია იქნება, მეთოდი რომელიც დაკეტავს რესურსებს. პროგრამა სკრინზე მარტივია, ფაილში წერს Hello-ს.

რომელიც დესკთოფზეა. კომპილირების შემდგომ:


მაგალითი 4:
Try/cacth ბლოკში კლასების გამოძახების იერარქიას აქვს მნიშვნელობა.
როდესაც cacth ბლოკში იწყებთ პრობლემებზე გამკლავებას კლასები უნდა გამოიძახოთ იერარქიულად, დაბლიდან მაღლა, ანუ შვილები მაღლა და მშობლები დაბლა. ნახეთ მაგალითი:

ქვე კლასზე გამკლავება ხდება სუპერ კლასის შემდგომ, გამომდინარე აქედან კომპილატორი ქვე კლასამდე არასდროს მიდის იმიტომ რო სუპერ კლასი უმკლავდება ორივე პრობლემას, თუ გსურთ სათითაოდ გაუმკლავდეთ გამონაკლისებს უნდა დაიცვათ იერარქია.

მეთოდის დეფინირების გასწვრივ ხედავთ რო ორ გამონაკლის ვისვრით, ვინაიდან FileNotFound არის IO-ს ქვე კლასი არ არსებობს აუცილებლობა რო მისი დეკლალირებაც მოახდინოთ, რადგან IO-ს დეკლალირება უკვე მოიცავს ყველა  მის ქვე კლას. შეგიძლიათ დაწეროთ შემდეგნაირად.

და მიაღწიოთ იგივე შედეგს. Throws  საკვანძო სიტყვით შეგიძლიათ განუსაზღვრელი ოდენობის გამონაკლისების გადასროლა, მაგრამ ერთი კლასი თუ სუპერ კლასია მეორესი ამის აუცილებლობა არ არსებობს, კოდი ამ გზით უფრო წაკითხვადი ხდება. Throw რატო გვაქ გამოყენებული ხვდებით უკვე ალბათ, მეთოდის დეკლარირებაში ნათქვამია რო ეს მეთოდი გადაისვრის გამონაკლის მაგრამ ჩვენ გვინდა რო მას გაუმკლავდეთ ადგილზე ამიტომაც ვისვრით try  ბლოკიდან ხელოვნურად, რადგან try   ბლოკში არ არის კოდი რომელიც გადაისვრის გამონაკლის ავტომატურად. 

                             გამონაკლისის გავრცელება(propagating exception)


თქვენ არ ხართ ვალდებული გაუმკლავდეთ გამონაკლის, გადმოსროლილს მეთოდიდან რომლის გამოძახებაც გიწევთ. თუ ამის აუცილებლობას არ ხედავთ, ან არ გსურთ ამ კონკრეტულ მეთოდში გაუმკლავდეთ გამონაკლის შეგიძლიათ ის გადააწოდოთ ნებისმიერ სხვა მეთოდს. ამ პროცეს propagating exception ქვია. თუ ასე მოიქცევით მაშინ უნდა მოახდინოთ დეფინირება გადასროლის იგივე სახელით, იმ მეთოდის გასწვრის სადაც გამოიძახეთ მეთოდი რომელიც ისვრის გამონაკლის. ნახეთ მაგალითი:

მეთოდი 1 აწოდებს პრობლემას მეორეს, მეორე მესამეს და მეოთხე უმკლავდება, დააკვირდით ვირტუალური მანქანა როგორი იერარქიით კითხულობს მეთოდებს. :

წაიკითხა ყველა მეთოდი ზემოდან ქვემოთ სტაკ მეხსიერებაში და მხოლოდ ამის შემდგომ დაუბრუნდა მეოთხე მეთოდს სადაც ციფრი 4 უნდა გამოიტანოს ეკრანზე.
ალბათ გაინტერესებთ, როდის უნდა მოახდინოთ პრობლემის გადაწოდება სხვა მეთოდზე, სიტუაციას გააჩნია, ხშირ შემთხვევაში პროგრამისტს არ აქვს საშუალება გაუმკლავდეს ამა თუ იმ პრობლემას ადგილზევე ან უახლოეს მეთოდში მეხსიერებიდა, ამიტომ ახდენს მის გადაწოდებას სულ უფრო მაღლა, თუ მიდის მთავარ მეთოდამდე, მთავარ მეთოდში უმკლავდებით ყველა არსებულ გამონაკლის, მაგრამ ხდება ისე რო მაინც გიწევთ დამატებითი ერორის დამუშავება, დაუშვათ მონაცემთა ბაზის გახსნა და დახურვა, გადაისროლეთ მთავარ მეთოდამდე, დაამუშავეთ მთავარ მეთოდში და მიხვედით ფინალურ ბლოკამდე სადაც ხურავთ ბაზას, დახურვა ბაზის ცალკე ისვრის გამონაკლის, თუ ძირითად მეთოდში გამონაკლისის დამუშავება არ მოხდა ერთადერთი რისი გაკეთებაც მოგიხდებათ ეს არის რომ აცნობოთ მომხმარებელს კავშირის გაწყვეტის შესახებ და დახუროთ ბაზა.  ეს იმას არ ნიშნავს რო აუცილებლად ასე უნდა მოიქცეთ,  არის იშვიათი სიტუაციები როცა ამის გაკეთება გიწევთ.

ამდენი რომ არ იფიქროთ და იწვალოთ ჯავა 7-ან გამონაკლისებს დაემატა try/catch with resources.

                                                             try/catch with resources.

ჯავა 7-ის გამოსვლის შემდეგ  გამონაკლისებს დაემატა  try/catch with resources ოპერაცია, რაც ნიშნავს იმას რომ პროგრამისტს ეძლევა საშუალება პირდაპირ მაოხდინოს პრობლემური ოპერაციის წარმოება  try ველზე, მეთოდის სახით და ავტომატურად დაკეტოს იგი. ნახეთ მაგალითი:

 დააკვირდით  try ველს, ეს გახლავთ try რესურსებთან ერთად, რომელიც არ მოითხოვს რესურსის დაკეტვას, ანუ ფინალური ბლოკი საერთოდ ქრება ოპერაციებიდან, სკრინზე ქეჩ ბლოკი არ არის მაგრამ შეიძლება დამატება, როდესაც try ველზე დასრულდება ოპერაცია ის დაიკეტება ავტომატურად რადგან გარკვეული კლასები გამონაკლისიდან ახდენენ იმპლემენტაციას closeable და autoclosable ინტერფეისების რომლებიც უმკლავდებიან რესურსების დახურვას, გამონაკლისი რომელსაც ამ კონკრეტულ მაგალითზე try ველი გადაისვრის, პირდაპირ მოხვდება გარე სამყაროში, გამონაკლისი რომელიც გამოიწვია ფაილის დახურვამ ქრება, try-ს რესურსებით გამოყენება მედლის მეორე მხარეა, ის ასრულებს ოპერაციებს სრულიად შებრუნებულად ვიდრე სტანდარტული try/cacth/finally ველები, try/cacth/finally გარე სამყაროში ხვდება ფინალური ბლოკიდან გადასროლილი გამონაკლისი, მაგალითად ფაილი თუ არ დაიხურა ის გამოიწვევს გამონაკლის და მოხვდება გარე სამყაროში, try ველიდან გადასროლილი გამონაკლისი კი გაქრება, ამ კონკრეტულ მაგალითში კი გარე სამყაროში ხვდება try ველიდან გადასროლილი გამონაკლისი და იკარგება დახურვის გამონაკლისი.  შესაძლებელია უამრავი რესურსი იქონიოთ try ველზე და დახუროთ ერთდროულად ყველა ერთ ქეჩ ველზე. ნახეთ მაგალითი:

სკრინზე ოპერაციები ნაჩვენებია მხოლოდ და მხოლოდ მაგალითისთვის. FileSystemException-ის ქონა აქ აუცილებლობას არ წარმოადგენს, ერთი IO გამონაკლისითაც შეიძლება პრობლემაზე გამკლავება მაგრამ როგორც ავღნიშნე, მხოლო და მხოლოდ მაგალითისთვის, შეგხვდებათ სიტუაცია როცა ერთ ქეჩ ველზე გაუმკლავდებით განსხვავებულ კლასებს და არა ერთი კლასის წარმომადგენლებს.  Try ველზე გვაქ ორი რესურსი  cacth ველზე ვიჭერთ ორ რესურს. სულ ეს არის try/catch რესურსებთან ერთად. რადგან ამდენი ვისაუბრეთ დახურვის ინტერფეისზე ვნახოთ რას წარმოადგენს ეს კონკრეტული ინტერფეისი,

                                                              CloseAble/AutoCloseAble

ამ ორი ინტერფეისის გამოყენება შეგიძლიათ ნებისმიერ სიტუაციაში, ნებისმიერ კლასთან, ისინი არ არიან შექმნილი მხოლოდ გამონაკლისებთან სამუშაოდ.  დამკეტ ინტერფეიში არის მხოლოდ ერთი მეთოდი და ის გამოიყურება შემდეგაირად:

ფოტოზე ხედავთ 2 მეთოდს, ერთი ჩემი შექმნილია, მეორე AutoCloseable
ინტერფეისის აბსტრაკტული მეთოდია, რომელიც გადავწერე. რის შემდგომაც ვიყენებთ საკუთარ დამკეტ კლას პროგრამაში.

დააკვირდით, ფოტოზე არსად არ არის გამოძახებული close() მეთოდი, თუმცა კომპილირების შემდგომ,

ის ახდენს კოპილირებას ავტომატურ რეჟიმში, სწორედ ეგეთ რეჟიმში დაიხურება ყველა თქვენი რესურსი, ძალიან გამოსადეგი და კომფორტული ინტერფეისია, რომელიც კოდს საგრძნობლად ამცირებს და უფრო წაკითხვადს ხდის. თუ რა დგას close() მეთოდის უკან, როგორ მუშაობს ის და რატო ახდენს ავტომატურად დახურვას ამას არ აგიხსნით, ინტერესი თუ გაგიჩდათ მოიძიეთ მასალა.


               შემოწმებული და შეუმოწმებელი გამონაკლისის დადებითი და უარყოფითი მხრეები:

მაგალითი:

შემოწმებული გამონაკლისი.
იგივე მაგალითზე ვნახოთ შეუმოწმებელი გამონაკლისი. პირველი რისი გაკეთებაც მომიწია შევქმენი იგივე კლასი ამ ჯერად მემკვიდრე RunTimeException კლასის.

და შემდგომ ზუსტად იგივე ოპერაცია გავიმეორე რაც მაღლა სკრინზეა მოცემული.

დააკვირდით კოდში სხვაობებს. მეთოდის დეფინიციიდან გაქრა საკვანძო სიტყვა throws, გამომდინარე აქედან მეთოდი რომელიც გამოიძახებს someNumber() მეთოდს არ ხდება იძულებული გაუმკლავდეს გამონაკლის ან გადააწოდოს ის სხვა მეთოდს მეხსიერებაში. მთავარ მეთოდში კი მას ჩვეულებრივად უმკლავდებით, როგორც ესეთი ორივეზე გამკლავება ხდება try/cacth ოპერაციების მეშვეობით, ერთი დიდი განსხვავებით. შეუმოწმებელ გამონაკლისამდე არ უნდა მივიდეს პროგრამისტი, ამისთვის მას ყველა ატრიბუტი გააჩნია.

ვნახეთ როგორ მუშაობს ორივე გამონაკლისი, ვნახეთ რა სხვაობაა მათ შორის კოდურ დონეზე, დროა განვიხილოთ მათი დადებითი და უარყოფითი მხარეები. უმრავლესობა ჯავა წიგნების აკეთებს ასეთ დეფინიციას,  „გამოიყენეთ შემოწმებული გამონაკლისები სიტუაციაში საიდანაც კოდმა პრობლემას თავი უნდა დააღწიოს და გამოიყენეთ შეუმოწმებელი გამონაკლისები მაშინ,  როცა ხედავთ რო თქვენი კოდი პრობლემას ვეღარ გაექცევა, “ ჩემი აზრით კოდი ნებისმიერ სიტუაციაში უნდა გაუმკლავდეს პრობლემას, შემოწმებული იქნება ის თუ შეუმოწმებელი. ისეთ პრობლემებსაც კი როგორიც არის NullPointerException, IllegalArgumentException  და სხვანი, რატომ? შეიძლება ოპერაცია ვერ შესრულდეს, მაგრამ აპლიკაცია ცოცხალი უნდა დარჩეს და გააგრძელოს დანარჩენი ოპერაციების წარმოება, ერთადერთი სიტუაცია როდესაც ნორმალურად შეიძლება ჩაითვალოს პროგრამის გაჩერება არის მისი სტარტირების დროს, რადგან თუ ვერ პოულობს ფაილს რომელიც დაეხმარება სრულ ფასოვან ფუნქციონირებაში, ჯობია გაჩერდეს და გაითიშოს.  აქედნ დასკვნა, ჩემი რჩევა იქნება რო გამოიყენოთ ორივე სახის გამონაკლისი, როგორ და სად გამოიყენეთ თქვენზეა დამოკიდებული, ბევრი გეტყვით როდესაც ორივეს იყენებთ ხშირად ხდება კოდის არევა, არ გახსოვს რომელი, რომელი სახის გამონაკლისია მაგრამ თუ სწორად დაასათაურებთ გამონაკლისებს არანაირი დაბრკოლების შექმნელი ეგ არგუმენტი არ იქნება, ერთი სიტყვით გააკეთეთ ის რასაც კონკრეტულ მომენტში აზრიან გადაწყვეტილებად ჩათვლით. (თუნდაც ეს გადაწყვეტილება უაზრო აღმოჩდეს გარკვეული პერიოდის მერე)
დადებითი მხარეეები:

1.     შეუმოწმებელი გამონაკლისი- შემოწმებული გამონაკლისი გადასროლილი მეთოდის მიერ ხდება მეთოდის ნაწილი, რის გამოც რთული ხდება მასზე სხვა გამონაკლისის დამატება სხვა კლასებში და ინტერფეისებში. (შემოწმებულის მინუსი გახლავთ შეუმოწმებელის პლიუსი)
ონტრ-არგუმენტი: ეს არანაირ პრობლემას არ წარმოადგენს თუ მეთოდიდან გადავისვრით სუპერ კლას, მომავალში მას ადვილად დავამატებთ სხვა გამონაკლისებს, რომლებიც აუცილებლად უნდა იყვნენ სუპერ კლასის ქვე კლასები.  არგუმენტი და კონტრ-არგუმენტი გვაიძულებს ვიფიქროთ, უკეთესი ხომ არ იქნება მსგავს სიტუაციაში გამოვიყენოთ შეუმოწმებელი გამონაკლისი?
2.  შემოწმებული გამონაკლისი -  შეუმოწმებელი გამონაკლისი არ ახდენს დეკლალირებას რომელი გამონაკლისის სროლა შეუძლია, რაც ავტომატურად რთულს ხდის მასზე გამკლავების პრინციპებს.
კონტრ-არგუმენტი: უმეტეს შემთხვევაში კოდის წერის დროს თქვენ ვერაფერს იზამთ გარდა იმისა რო მიაწოდებთ მომხმარებელს ინფორმაციას ერორის გამოწმვევ მიზეზებზე, ამიტომ არანაირი მნიშვნელობა არ აქვს თქვენი გამონაკლისი შემოწმებული იქნება თუ შეუმოწმებელი, ორივეზე გამკლავება გიწევთ მაინც.
3.  შეუმოწმებელო გამონაკლისი - შემოწმებული გამონაკლისის მეთოდიდან გადასროლის დროს მაღალი დონის მეთოდები იტვირთება და ბოლოსკენ მას უამრავ გამონაკლისზე გამკლავება უწევს ერთდროულად. წარმოიდგინეთ ასობით კლასი გაქვთ, ათასობით მეთოდი სადაც სავარაუდოდ მესამედი მაინც ისვრის გამონაკლის, მეხსირებაში როცა ვახდენთ მათ გადაწოდებას, მაღალი დონის (დაუშვათ main) მეთოდი დაიტვირთება ასობით გამონაკლისით, რომელზეც გამკლავება მოგიხდებათ და რომელიც წაიღებს ათასობით ველს, უამრავ დროს და ენერგიას

ფოტოზე მოცემული პრინციპით.
       კონტრ-არგუმენტი: მაღლა ვისაუბრეთ როგორ შეუძლია ერთ        გამონაკლის, მეორის შეთავსება თუ მისი ტიპის არის. ამ სიტუაციაში ეგ იქნება ჩვენი კონტრ-არგუმენტი, არ აქვს მნიშვნელობა რამდენი გამონაკლისი გაქვს, მათი კომბინირება შეიძლება და ბოლოში სადაც გამკლავებას გადავწყვეტთ შეიძლება გვექნეს 2 სუპერ გამონაკლის, 1 შეითავსებს შეუმოწმებელ გამონაკლისებს მეორე შემოწმებულებს. დაახლოებით ეგეთი პრინციპით, რომელიც ფოტოზეა  ნაჩვენები.

ყველა გამონაკლისი ვაქციეთ ერთ გამონაკლისდან და ის მატარებელი ხდება ყველას შიგთავსის. შეგვიძლია საკუთარი გამონაკლისიც ვაქციოთ სუპერ ტიპად და მას მივცეთ ყველა გამონაკლისი გამკლავებისთვის. დაახლოებით შემდგი პრინციპით.

ლოგიკა მარტივად აღსაქმელია.
4.     შემოწმებული გამონაკლისი - შეუმოწმებელი გამონაკლისის დავიწყება მარტივია, არანაირი ინდიკატორი არ არსებობს მისი არსებობის და კომპილატორი არ გვაიძულებს ის გადავაწოდოთ სხვა მეთოდებს ან გაუმკლავდეთ.
კონტრ-არგუმენტი: არანაირი გარანტია არ არსებობს იმისა რო ნებისმიერი მეთოდი ნებისმიერ აპლიკაციაში არ ისვრის შეუმოწმებელ გამონაკლის, ამიტომ ილუზია რო ყველა გამონაკლისი იყოს შემოწმებული, ხედავდე მას და უმკლავდებოდე არის პარადოქსული.
   
აქედან დასკვნა, რაც თავიდანვე ავღნიშნე, უნდა გამოიყენოთ ორივე, როგორ გამოიყენეთ ორივეს თქვენ პრაგმატულობაზეა დამოკიდებული.

                                                                 Logging Exceptions

ხშირს შემთხვევაში როდესაც მუშაობთ ბიზნეს აპლიკაციებზე, სერვერ აპლიკაციებზე ან თუნდაც ვებ აპლიკაციებზე მომხმარებლისთვის აუცილებელია იქონიოს ინფორმაცია მიმდინარე და არსებული გადაცდომების შესახებ, მარტივი მიზეზის გამო, მსგავს აპლიკაციებში System.out.println() მეთოდს ვერ გამოიყენებთ კონზოლში ინფორმაციის გამოსატანად, საერთოდ რეალური პროგრამირების დროს კონზოლში ინფორმაციის გამოტანა თითქმის არ ხდება, ჩდება კითხვა როგორ მივიტანოთ გამონაკლისი მომხარებლამდე? სად უნდა ნახოს კლიენტმა რა შეცდომები დაუშვა თუ მისი აპლიკაცია შეწყვეტს მუშაობას? ამისთვის არსებობს საკმაოდ მოხერხებული ბიბლიოთეკა და მას Logger ქვია. მისი გამოყენება შესაძლებელია ბევრგან მაგრამ ჩვენ განვიხილავთ ლოგს გამონაკლისთან მუშაობის დროს.

როდესაც ქმნით აპლიკაციას ხშირად ჩნდება კითხვა, საიდან შეუშვათ გამონაკლისი ლოგ ფაილში? არსებობს რამოდენიმე ვარიანტი:
1.     გამონაკლისი შეუშვათ ფაილში ეგრევე მისი გამოწვევის დროს
2. შეუშვათ გამონაკლისი პროგრამის შუა ნაწილიდან ფაილში, საიდანაც საკმარის ინფორმაციაზე მიგვიწვდება ხელი.
3. შეუშვათ გამონაკლისი ფაილში სუპერ მეთოდიდან, საიდანაც თითქმის ყველა გამონაკლისზე მიგვიწვდება ხელი, როგორც წესი.  
მაგალითებს საიდან უკეთესია ფაილში ინფორმაციის შეტანა არ გაჩვენებთ, თქვენ თვითონ გადაწყვიტავთ, მე უბრალოდ განახებთ როგორ ხდება ამ ოპერაციის წარმოება.

ეს არის კლასი, კონსტრუკტორით მხოლოდ, რომელიც მიიღებს ფაილის სახელს და ისვრის გამონაკლის.

შემდგომ ვქმნით ობიეკტს ამ კლასისგან და ვაწოდებთ ფაილის სახელს,

უთითებთ რო შექმნას და შეინახოს ფაილის კონკრეტულ მისამართზე.
და ვიწყებთ ინფორმაციის შეტანას ფაილში, რა სახის ინფოა ფაილში მაგას დაშვების ლეველი გვეუბნება, ჩვენ შემთხვევაში უბრალოდ ინფორმაციის მატარებელი იქნება. კომპილირების შემდგომ:

არსებობს განსხვავებული შესვლის კლასები, თუ დაგაინტერესათ ოპერაციამ მოიძიეთ მასალა ინრეტნეტში.

                                                    ჩაბუდებული try/catch ბლოკები

გამონაკლისების ჩაბუდება საკმაოდ გამოყენებადი პრაკტიკა გახლავთ პროგრამირებაში, დაუშვათ გვაქ try/catch ბლოკი რომელიც უმკლავდება გამონაკლის, მაგრამ კოდის წერის დროს წავაწყდით მეორე გამონაკლის, რომელსაც უნდა გაუმკლავდეთ, მაშინ ვახდენთ მის ჩაბუდებას, შიდა გამონაკლისი უკლავდება ლოკალურად გამოწვეულ პრობლემას როდესაც ძირითადი try/catch ბლოკი უმკლავდება უფრო მაღალი დონის გამონაკლის. ნახეთ მაგალითი.

  შესაძლებელია მრავალ საფეხურიანი ჩაბუდების წარმოება. 

                                                       საკუთარი გამონაკლისის შექმნა

საკუთარი გამონაკლისი შეიძლება იყოს ორი ტიპის, შემოწმებული და შეუმოწმებელი. მაგალითები, რომელსაც ფოტოებზე ნახავთ არის შემოწმებული გამონაკლი.
1. ვქნით საბანკო გამონაკლის.:

პირველი კონსტრუკტორი მომხმარებელს საშუალებას მიცემს ისროლოს ცარიელი გამონაკლისი, მერე კონსტრუკტორიდან ისვრის გამონაკლის მესიჯით, და მესამე კონსტრუკტორი ისვრის მესიჯს, გამომწვევ მიზეზებთან ერთად.
2. ვქმნით 2 ქვე გამონაკლის, რომლებიც მხოლოდ მესიჯის მატარებლები იქნებიან:



3. ვმქნით ობიეკტს მომხმარებლისთვის:
სადაც გვაქ ორი ძირითადი მეთოდი, რომლებიც თანხის გატანა შემოტანას აკონტროლებენ და ისვრიან ჩვენ მიერ შექმნილ გამონაკლისებს. 
4. ვიყენებთ მეთოდებს:
ამის შემდგომ თუ მომხმარებელი შეეცდება შეიტანოს ანგარიშზე 30000 ლარზე მეტი, დეპოსიტ მეთოდი ისვრის გამონაკლის, თუ შეეცდება გაიტანოს 15000 ლარზე მეტი ამუშავდება მეორე გამონაკლისი.  საკმადო პრიმიტიულია პროგრამა და მარტივად გასაგები. შედეგი თუ გაინტერესებთ გადაიწერეთ კოდი და გაუშვით თქვენ ხელსაწყოში, მე დაგემშვიდობებით, მომავალ შეხვედრამდე. 

No comments:

Post a Comment