JavaRush /Java блогы /Random-KK /Java тіліндегі ерекшеліктер: ұстау және өңдеу

Java тіліндегі ерекшеліктер: ұстау және өңдеу

Топта жарияланған
Сәлеметсіз бе! Мен сізге бұны жек көремін, бірақ бағдарламашы жұмысының үлкен бөлігі қателермен айналысады. Және көбінесе - өздерімен. Қателік жасамайтын адамдар болмайды. Және мұндай бағдарламалар да жоқ. Әрине, қатемен жұмыс істегенде ең бастысы оның себебін түсіну. Бағдарламада мұндай себептердің көп болуы мүмкін. Бір кезде Java жасаушыларына сұрақ туындады: бағдарламалардағы осы өте ықтимал қателермен не істеу керек? Олардан мүлдем аулақ болу шындыққа жанаспайды. Бағдарламашылар тіпті елестету мүмкін емес нәрсені жаза алады :) Бұл тілге қателермен күресу механизмін құру керек дегенді білдіреді. Басқаша айтқанда, бағдарламада қандай да бір қате орын алса, одан әрі жұмыс істеу үшін сценарий қажет. Қате орын алған кезде бағдарлама нақты не істеуі керек? Бүгін біз бұл механизммен танысамыз. Және ол «Ерекшеліктер » деп аталады .

Java тіліндегі ерекшелік дегеніміз не

Ерекшелік - бұл бағдарламаның жұмыс істеуі кезінде орын алған ерекше, жоспардан тыс жағдай. Java тілінде ерекше жағдайлардың көптеген мысалдары болуы мүмкін. Мысалы, сіз файлдағы мәтінді оқитын және консольге бірінші жолды көрсететін code жаздыңыз.
public class Main {

   public static void main(String[] args) throws IOException {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
       String firstString = reader.readLine();
       System.out.println(firstString);
   }
}
Бірақ мұндай файл жоқ! Бағдарламаның нәтижесі ерекшелік болады - FileNotFoundException. Қорытынды:

Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
Әрбір ерекшелік Java тіліндегі бөлек сыныппен ұсынылған. Барлық ерекшелік сыныптары ортақ «атадан» – ата-аналық сыныптан келеді Throwable. Ерекшелік класының атауы әдетте оның пайда болу себебін қысқаша көрсетеді:
  • FileNotFoundException(Файл табылмады)
  • ArithmeticException(математикалық операцияны орындау кезіндегі ерекшелік)
  • ArrayIndexOutOfBoundsException(массив ұяшығының саны оның ұзындығынан тыс көрсетіледі). Мысалы, ұзындығы 10 массив үшін ұяшық массивін [23] консольге шығаруға тырыссаңыз.
Java тілінде 400-ге жуық осындай сыныптар бар! Неге сонша көп? Бағдарламашыларға олармен жұмыс істеуді ыңғайлы ету үшін. Елестетіп көріңізші: сіз бағдарлама жаздыңыз және ол іске қосылғанда келесідей ерекше жағдайды шығарады:
Exception in thread "main"
Ух-ух :/ Ештеңе анық емес. Бұл қандай қателік және қайдан шыққаны белгісіз. Пайдалы ақпарат жоқ. Бірақ осындай алуан түрлі сыныптардың арқасында программист өзі үшін ең бастысын алады - қатенің түрі мен оның ықтимал себебі сыныптың атауында қамтылған. Ақыр соңында, бұл консольде мүлдем басқа нәрсе:
Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
Мәселе қандай болуы мүмкін және мәселені шешу үшін «қай бағытта қазу керек» бірден түсінікті болады! Ерекшеліктер, сыныптардың кез келген даналары сияқты, нысандар болып табылады.

Ерекшеліктерді ұстау және өңдеу

Java тілінде ерекше жағдайлармен жұмыс істеу үшін арнайы code блоктары бар: try, catchжәне finally. Ерекшеліктер: ұстап алу және өңдеу - 2Бағдарламашы ерекше жағдайларды күтетін code блокта орналастырылған try. Бұл бұл жерде ерекше жағдай міндетті түрде болады дегенді білдірмейді. Бұл сонда болуы мүмкін дегенді білдіреді және бағдарламашы бұл туралы біледі. Сіз қабылдайтын қате түрі блокқа catch(«ұстап алу») орналастырылған. Бұл сондай-ақ ерекше жағдай орын алған жағдайда орындалуы керек барлық code орналастырылған жер. Міне, мысал:
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {

       System.out.println("Error! File not found!");
   }
}
Қорытынды:

Ошибка! Файл не найден!
Біз codeты екі блокқа орналастырамыз. Бірінші блокта «Файл табылмады» қатесі орын алуы мүмкін деп күтеміз. Бұл блок try. Екіншісінде біз бағдарламаға қате орын алған жағдайда не істеу керектігін айтамыз. Сонымен қатар, қатенің белгілі бір түрі бар - FileNotFoundException. Егер біз catchбасқа ерекшелік класын блок жақшаларына өткізсек, ол ұсталмайды.
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (ArithmeticException e) {

       System.out.println("Error! File not found!");
   }
}
Қорытынды:

Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
Блоктағы code catchжұмыс істемеді, өйткені біз бұл блокты ұстап алу үшін «конфигурацияладық» ArithmeticExceptionжәне блоктағы code tryбасқа түрді - FileNotFoundException. Біз сценарий жазған жоқпыз FileNotFoundException, сондықтан бағдарлама консольде әдепкі бойынша көрсетілетін ақпаратты көрсетеді FileNotFoundException. Бұл жерде 3 нәрсеге назар аудару керек. Бірінші. Тексеру блогындағы codeтың кез келген жолында ерекше жағдай орын алғаннан кейін, одан кейінгі code енді орындалмайды. Бағдарламаның орындалуы бірден блокқа «секіреді» catch. Мысалы:
public static void main(String[] args) {
   try {
       System.out.println("Divide a number by zero");
       System.out.println(366/0);//this line of code will throw an exception

       System.out.println("This");
       System.out.println("code");
       System.out.println("Not");
       System.out.println("will");
       System.out.println("done!");

   } catch (ArithmeticException e) {

       System.out.println("The program jumped to the catch block!");
       System.out.println("Error! You can't divide by zero!");
   }
}
Қорытынды:

Делим число на ноль 
Программа перепрыгнула в блок catch! 
Ошибка! Нельзя делить на ноль! 
Екінші жолдағы блокта tryбіз санды 0-ге бөлуге тырыстық, нәтижесінде ерекшелік болды ArithmeticException. Осыдан кейін блоктың 6-10 жолдары tryенді орындалмайды. Біз айтқанымыздай, бағдарлама бірден блокты орындауға кірісті catch. Екінші. Бірнеше блоктар болуы мүмкін catch. Егер блоктағы code tryбір емес, бірнеше ерекшелік түрлерін шығара алса, олардың әрқайсысы үшін өз блокыңызды жаза аласыз catch.
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       System.out.println(366/0);
       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {

       System.out.println("Error! File not found!");

   } catch (ArithmeticException e) {

       System.out.println("Error! Division by 0!");

   }
}
Бұл мысалда біз екі блокты жаздық catch. Егер блокта tryорын алса FileNotFoundException, бірінші блок орындалады catch. Егер орын алса ArithmeticException, екіншісі орындалады. Сіз кем дегенде 50 блок жаза аласыз.Бірақ catch, әрине, 50 түрлі қате жіберетін codeты жазбағаныңыз дұрыс :) Үшіншіден. Сіздің codeыңыз қандай ерекше жағдайларды тудыруы мүмкін екенін қайдан білесіз? Әрине, сіз кейбіреулер туралы болжауға болады, бірақ бәрін өз ойыңызда ұстау мүмкін емес. Сондықтан Java компиляторы ең көп таралған ерекшеліктер туралы біледі және олардың қандай жағдайларда орын алуы мүмкін екенін біледі. Мысалы, егер сіз code жазсаңыз және компилятор оның жұмысы кезінде ерекше жағдайлардың 2 түрі болуы мүмкін екенін білсе, сіз оларды өңдемейінше сіздің codeыңыз құрастырылмайды. Мұның мысалдарын төменде көреміз. Енді ерекше жағдайларды өңдеу туралы. Оларды өңдеудің 2 жолы бар. Біз біріншісін кездестірдік - әдіс блокта ерекше жағдайды дербес өңдей алады catch(). Екінші нұсқа бар - әдіс қоңыраулар стегін жоғарылатуы мүмкін. Бұл нені білдіреді? printFirstString()Мысалы, біздің сыныпта файлды оқитын және оның бірінші жолын консольге көрсететін әдіс бар :
public static void printFirstString(String filePath) {

   BufferedReader reader = new BufferedReader(new FileReader(filePath));
   String firstString = reader.readLine();
   System.out.println(firstString);
}
Қазіргі уақытта біздің code құрастырылмайды, себебі оның өңделмеген ерекше жағдайлары бар. 1-жолда сіз файлға жолды көрсетесіз. Компилятор мұндай codeтың оңай әкелетінін біледі FileNotFoundException. 3-жолда сіз файлдағы мәтінді оқисыз. IOExceptionБұл процесте енгізу-шығару (кіріс-шығару) кезінде қате оңай орын алуы мүмкін . Енді компилятор сізге былай дейді: «Жігіт, осы ерекшеліктердің бірі орын алса, не істеу керектігін айтпайынша, мен бұл codeты мақұлдамаймын немесе оны құрастырмаймын. Және олар сіз жазған code негізінде болуы мүмкін! » . Баратын жер жоқ, екеуін де өңдеу керек! Бірінші өңдеу опциясы бізге бұрыннан таныс: codeты блокқа орналастырып try, екі блокты қосу керек catch:
public static void printFirstString(String filePath) {

   try {
       BufferedReader reader = new BufferedReader(new FileReader(filePath));
       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {
       System.out.println("Error, file not found!");
       e.printStackTrace();
   } catch (IOException e) {
       System.out.println("Error while inputting/outputting data from file!");
       e.printStackTrace();
   }
}
Бірақ бұл жалғыз нұсқа емес. Біз әдіс ішіндегі қатеге сценарий жазудан аулақ бола аламыз және ерекше жағдайды жоғарыға лақтырамыз. throwsБұл әдіс мәлімдемесінде жазылған кілт сөзі арқылы жасалады :
public static void printFirstString(String filePath) throws FileNotFoundException, IOException {
   BufferedReader reader = new BufferedReader(new FileReader(filePath));
   String firstString = reader.readLine();
   System.out.println(firstString);
}
Сөзден кейін throwsбіз үтірмен бөлінген, бұл әдіс жұмыс кезінде шығара алатын ерекшеліктердің барлық түрлерін тізімдейміз. Бұл не үшін жасалып жатыр? Енді бағдарламадағы біреу әдісті шақырғысы келсе printFirstString(), ол ерекше жағдайларды өңдеуді өзі жүзеге асыруы керек. Мысалы, бағдарламаның басқа бөлігінде сіздің әріптестеріңіздің бірі әдісіңізді деп атайтын әдісті жазды printFirstString():
public static void yourColleagueMethod() {

   //...your colleague's method does something

   //...and at one moment calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Eugene\\Desktop\\testFile.txt");
}
Қате, code құрастырылмайды! Біз әдісте printFirstString()қателерді өңдеу сценарийін жазған жоқпыз . Сондықтан бұл әдісті қолданатындардың иығына міндет жүктеледі. Яғни, әдіс yourColleagueMethod()қазір бірдей 2 опцияға тап болады: ол не оған «келетін» екі ерекшеліктерді де көмегімен өңдеуі керек try-catchнемесе оларды әрі қарай жіберуі керек.
public static void yourColleagueMethod() throws FileNotFoundException, IOException {
   //...the method does something

   //...and at one moment calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Eugene\\Desktop\\testFile.txt");
}
Екінші жағдайда, өңдеу стектегі келесі әдістің иығына түседі - қоңырау шалатын әдіс yourColleagueMethod(). Сондықтан мұндай механизм «ерекшелікті жоғары лақтыру» немесе «жоғарыға өту» деп аталады. Ерекшеліктерді пайдаланып шығарған кезде throws, code құрастырылады. Осы кезде құрастырушы: «Жарайды, жарайды. Сіздің codeыңызда көптеген ықтимал ерекшеліктер бар, бірақ мен оны бәрібір құрастырамын. Біз бұл әңгімеге қайта ораламыз!» Бағдарламаның бір жерінде оның ерекше жағдайларын өңдемеген әдісті шақырған кезде, компилятор өз уәдесін орындайды және олар туралы қайтадан еске салады. Соңында біз блок туралы айтатын боламыз finally(сөз сөзді кешіріңіз). Бұл триумвираттың ерекше жағдайларын өңдеудің соңғы бөлігі try-catch-finally. Оның ерекшелігі - ол кез келген бағдарлама жұмысының сценарийі бойынша орындалады.
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {
       System.out.println("Error! File not found!");
       e.printStackTrace();
   } finally {
       System.out.println("And here is the finally block!");
   }
}
Бұл мысалда блок ішіндегі code finallyекі жағдайда да орындалады. Егер блоктағы code tryтолығымен орындалса және ерекше жағдай жасамаса, блок соңында іске қосылады finally. Егер ішіндегі code tryүзіліп , бағдарлама блокқа өтсе catch, ішіндегі code орындалғаннан кейін catchблок әлі таңдалады finally. Ол не үшін қажет? Оның негізгі мақсаты codeтың қажетті бөлігін орындау; жағдайларға қарамастан толтырылуы тиіс бөлік. Мысалы, ол көбінесе бағдарлама пайдаланатын кейбір ресурстарды босатады. Біздің codeта біз файлдағы ақпаратты оқу және оны файлға жіберу үшін ағынды ашамыз BufferedReader. Біздікі readerжабылып, ресурстарды босату керек. Бұл кез келген жағдайда жасалуы керек: бағдарлама күткендей жұмыс істей ме немесе ерекше жағдай жасай ма, маңызды емес. Мұны блокта жасау ыңғайлы finally:
public static void main(String[] args) throws IOException {

   BufferedReader reader = null;
   try {
       reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {
       e.printStackTrace();
   } finally {
       System.out.println("And here is the finally block!");
       if (reader != null) {
           reader.close();
       }
   }
}
Енді біз бағдарлама жұмыс істеп тұрған кезде не болатынына қарамастан, біз пайдаланылған ресурстарға қамқорлық жасағанымызға толық сенімдіміз :) Ерекшеліктер туралы білуіңіз керек бұл ғана емес. Қателерді өңдеу - бағдарламалаудағы өте маңызды тақырып: оған бірнеше мақалалар арналған. Келесі сабақта біз ерекше жағдайлардың қандай түрлері бар екенін және өзіңіздің ерекше жағдайыңызды қалай жасау керектігін үйренеміз :) Онда кездескенше!
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION