با عرض سلام و وقت بخیر خدمت کاربران سایت پی وی لرن. و کاربرانی که دوره کامل آموزش برنامه نویسی جاوا را دنبال می کنند. Exception (یا رویداد استثنایی) یک مشکل است که در طول اجرای یک برنامه رخ می دهد. هنگامی که یک Exception اتفاق می افتد، جریان طبیعی برنامه متوقف شده و برنامه به طور خودکار پایان می یابد، که این امر برای کاربران بسیار مشکل ساز خواهد بود. برای جلوگیری از این رخداد و مدیریت این خطاها باید با چگونگی کار با exception در جاوا آشنا شوید تا بتوانید خطاهای احتمالی را مدیریت کنید. برای آشنایی با چگونگی کار با exception در جاوا و متدهای exception در جاوا در ادامه ی این آموزش با ما همراه باشید.
در ادامه ی مباحث کار با exception در جاوا ابتدا شما را با دلایل رخ دادن exception آشنا کرده و سپس به چگونگی مدیریت آن می پردازیم.
exception ممکن است به دلایل مختلف رخ دهد. در زیر به برخی از دلایلی که ممکن است در آنها یک exception رخ دهد اشاره شده است:
برخی از این exception ها به دلیل خطای کاربر، و برخی توسط خطای برنامه نویس و همچنین توسط منابع فیزیکی ایجاد می شود.
بر اساس این، ما سه نوع exception داریم. شما باید آنها را درک کنید تا چگونگی کار با exception در جاوا را بدانید:
یک exception چک شده در زمان کامپایل برنامه ها رخ می دهد، و برنامه نویس می تواند با کدنویسی این exception ها را کنترل کند.
برای مثال، فرض می کنیم از کلاس FileReader در برنامه خود برای خواندن داده ها از یک فایل استفاده می کنید.
حالا اگر فایل مشخص شده در ساختار آن وجود نداشته باشد FileNotFoundException رخ می دهد.
مثال:
1 2 3 4 5 6 7 8 9 10 | import java.io.File; import java.io.FileReader; public class FilenotFound_Demo { public static void main(String args[]) { File file = new File("E://file.txt"); FileReader fr = new FileReader(file); } } |
اگر برنامه ی فوق را اجرا کنید با خطا یا exception زیر مواجه خواهید شد:
1 2 3 4 5 | C:\>javac FilenotFound_Demo.java FilenotFound_Demo.java:8: error: unreported exception FileNotFoundException; must be caught or declared to be thrown FileReader fr = new FileReader(file); ^ 1 error |
متد () read و () close از کلاس FileReader IOException ارائه می شوند.
پس کامپایلر از FileNotFoundException برای مدیریت IOException بهره می گیرد.
exception چک نشده که در زمان اجرای اجرا رخ می دهد به عنوان Exceptions Runtime نیز شناخته می شود.
این exception شامل اشکالات برنامه نویسی مانند اشتباهات منطقی یا استفاده نامناسب از API است.
این نوع Exceptions در زمان کامپایل نادیده گرفته می شود.
به عنوان مثال، فرض کنید آرایه ای از با اندازه ۵ عنصر را در برنامه خود اعلام کرده باشید.
سپس سعی می کنیم عنصر شماره ۶ را فراخوانی کنیم.
در این صورت یک خطای ArrayIndexOutOfBoundsExceptionexception رخ می دهد.
مثال:
1 2 3 4 5 6 7 | public class Unchecked_Demo { public static void main(String args[]) { int num[] = {1, 2, 3, 4}; System.out.println(num[5]); } } |
اگر کد فوق را کامپایل کرده و اجرا کنید با خطای زیر رو به رو خواهید شد:
1 2 | Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at Exceptions.Unchecked_Demo.main(Unchecked_Demo.java:8) |
تمام موارد حتما یک exception نیست. گاهی مشکلی فراتر از کنترل کاربر یا برنامه نویس رخ می دهد.
Error(خطا) معمولا در کد نادیده گرفته می شود چراکه شما نمی توانید تمام خطاها را در برنامه مدیریت کنید.
همه کلاسهای exception زیرمجموعه کلاس java.lang.Exception هستند. کلاس exception خود یک کلاس از زیر کلاس Throwable است.
به غیر از exception، زیرمجموعه دیگری به نام Error وجود دارد که از کلاس Throwable استخراج شده است.
Error ها شرایط غیرطبیعی هستند که در صورت شکستهای شدید اتفاق می افتد.
Error ها برای نشان دادن نوع خطای ایجاد شده از runtime environment استفاده می کند.
کلاس Exception دارای دو زیر شاخه اصلی کلاس IOException و کلاس RuntimeException است.
در زیر لیستی از متدهای مهم در کلاس Throwable موجود است:
ردیف | متد و توضیحات |
---|---|
۱ | public String getMessage() این یک پیام در مورد exception رخ داده شده نشان می دهد،این پیام در سازنده Throwable آغاز شده است. |
۲ | public Throwable getCause() علت exception را به عنوان یک شی Object Throwable نشان می دهد. |
۳ | public String toString() نام کلاس متصل به نتیجه ()getMessage را می دهد. |
۴ | public void printStackTrace() از متد () toString برای چاپ خطا استفاده می کند. |
۵ | public StackTraceElement [] getStackTrace() یک آرایه را که حاوی هر عنصر در پشته است، را بازمی گرداند. |
۶ | public Throwable fillInStackTrace() ردیابی پشته از شی Throwable را با ردیابی پشته فعلی پر می کند. |
یک بلوک try / catch در اطراف کدی قرار می گیرد که ممکن است یک exception را تولید کند.
کد در یک بلوک try / catch به عنوان کد حفاظت اشاره شده است و نحو استفاده از try / catch مانند زیر است
عبارت catch برای اعلام نوع exception و پیغام خطا به کاربر است.
مثال – در نمونه زیر یک آرایه با دو عنصر تعریف شده که کد برنامه سعی می کند به عنصر ۳ دسترسی پیدا کند.
در نتیجه یک خطا رخ می دهد، که ما آن را مدیریت می کنیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // File Name : ExcepTest.java import java.io.*; public class ExcepTest { public static void main(String args[]) { try { int a[] = new int[2]; System.out.println("Access element three :" + a[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception thrown :" + e); } System.out.println("Out of the block"); } } |
نتیجه ی اجرای کد فوق بصورت زیر خواهد بود:
1 2 | Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3 Out of the block |
بلوک try را می توان با بلوک های catch چندگانه نیز توسعه داد.
ساختار :
1 2 3 4 5 6 7 8 9 | try { // Protected code } catch (ExceptionType1 e1) { // Catch block } catch (ExceptionType2 e2) { // Catch block } catch (ExceptionType3 e3) { // Catch block } |
در کد فوق بلوک های چندگانه از catch ارائه شده که در هر بلوک Exception بررسی می شود.
اگر Exception مربوط به هر بلوک catch نباشد به بلوک catch بعدی منتقل شده و بررسی می شود.
مثال – کد زیر چگونگی استفاده از ساختار try/catch چندگانه را بخوبی نشان می دهد:
1 2 3 4 5 6 7 8 9 10 | try { file = new FileInputStream(fileName); x = (byte) file.read(); } catch (IOException i) { i.printStackTrace(); return -1; } catch (FileNotFoundException f) // Not valid! { f.printStackTrace(); return -1; } |
از جاوا ۷ به بعد ایجاد بلوک های catch چندگانه بصورت زیر ساده می شود:
1 2 3 | catch (IOException|FileNotFoundException ex) { logger.log(ex); throw ex; |
کلمه ی کلیدی throws برای بررسی یک Exception در یک متد استفاده می شود.
شما باید با استفاده از کلمه ی کلیدی throw یک Exception جدید را به اثبات برسانید.
اختلاف بین throws و throw در این است که:
throws برای متوقف کردن دستکاری یک Exception مورد استفاده قرار می گیرند.
throw برای اعلام خطا استفاده می شود.
مثال – متد زیر RemoteException را اجرا می کند :
1 2 3 4 5 6 7 8 9 | import java.io.*; public class className { public void deposit(double amount) throws RemoteException { // Method implementation throw new RemoteException(); } // Remainder of class definition } |
در یک متد می توانید تعیین کنید که بیش از یک exception مورد بررسی قرار بگیرد، در این صورت exception ها در لیستی جداگانه با کاما از هم جدا شده و اعلام می شود.
مثال:
1 2 3 4 5 6 7 8 9 | import java.io.*; public class className { public void withdraw(double amount) throws RemoteException, InsufficientFundsException { // Method implementation } // Remainder of class definition } |
بلوک finally در ساختار try/catch بعد از تمام بلوک های catch قرار گرفته و در صورتی که هیچکدام از بلوک های catch اجرا نشود این بلوک اجرا خواهد شد.
ساختار بلوک finally در ساختار try/catch:
1 2 3 4 5 6 7 8 9 10 11 | try { // Protected code } catch (ExceptionType1 e1) { // Catch block } catch (ExceptionType2 e2) { // Catch block } catch (ExceptionType3 e3) { // Catch block }finally { // The finally block always executes. } |
مثال:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class ExcepTest { public static void main(String args[]) { int a[] = new int[2]; try { System.out.println("Access element three :" + a[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception thrown :" + e); }finally { a[0] = 6; System.out.println("First element value: " + a[0]); System.out.println("The finally statement is executed"); } } } |
نتیجه ی اجرای کد فوق بصورت زیر خواهد بود:
1 2 3 | Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3 First element value: 6 The finally statement is executed |
نکات زیر را به خاطر بسپارید:
به طور کلی، هنگام استفاده از منابع مانند stream ، اتصالات و…، ما باید با استفاده از بلوک finally به صراحت آن را ببندیم.
مثال- در برنامه زیر، ما با استفاده از FileReader داده ها را از یک فایل می خوانیم و آن را با استفاده از نهایت بلوک finally می بندیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import java.io.File; import java.io.FileReader; import java.io.IOException; public class ReadData_Demo { public static void main(String args[]) { FileReader fr = null; try { File file = new File("file.txt"); fr = new FileReader(file); char [] a = new char[50]; fr.read(a); // reads the content to the array for(char c : a) System.out.print(c); // prints the characters one by one } catch (IOException e) { e.printStackTrace(); }finally { try { fr.close(); } catch (IOException ex) { ex.printStackTrace(); } } } } |
شما می توانید با استفاده از ساختار try-with-resources فایل هایی را در ساختار try/catch خوانده و آن ها را خطایابی کنید.
برای اینکار کافیست که شما دستورات مورد نظر را در داخل پرانتز ” () ” قرار دهید.
ساختار:
1 2 3 4 5 6 | try(FileReader fr = new FileReader("file path")) { // use the resource } catch () { // body of catch } } |
در زیر یک برنامه ی نمونه است که داده ها را در یک فایل با استفاده از ساختار try-with-resources می خواند:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import java.io.FileReader; import java.io.IOException; public class Try_withDemo { public static void main(String args[]) { try(FileReader fr = new FileReader("E://file.txt")) { char [] a = new char[50]; fr.read(a); // reads the contentto the array for(char c : a) System.out.print(c); // prints the characters one by one } catch (IOException e) { e.printStackTrace(); } } } |
نکات زیر باید در هنگام کار با ساختار try-with-resources در نظر گرفته بگیرید:
شما می توانید Exception های خود را در جاوا ایجاد کنید. در هنگام نوشتن کلاس های Exception خود نکات زیر را در ذهن داشته باشید:
ما می توانیم کلاس Exception خودمان را به صورت زیر تعریف کنیم:
1 2 | class MyException extends Exception { } |
شما فقط باید کلاس Exception را از قبل تعریف کنید تا Exception خودتان را ایجاد کنید.
اینها به عنوان Exception مورد بررسی قرار می گیرند.
کلاس ExecuteFundsException زیر یک استثناء تعریف شده توسط کاربر است که کلاس Exception را گسترش می دهد و آن را یک Exception بررسی می کند.
مثال:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // File Name InsufficientFundsException.java import java.io.*; public class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; } } |
کلاس زیر CheckingAccount شامل یک متد ()withdraw است که InsufficientFundsException را با throws اجرا می کند:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | // File Name CheckingAccount.java import java.io.*; public class CheckingAccount { private double balance; private int number; public CheckingAccount(int number) { this.number = number; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) throws InsufficientFundsException { if(amount <= balance) { balance -= amount; }else { double needs = amount - balance; throw new InsufficientFundsException(needs); } } public double getBalance() { return balance; } public int getNumber() { return number; } } |
در برنامه BankDemo زیر، متدهای ()deposit و () withdraw توسط CheckingAccount فراخوانی می شود:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // File Name BankDemo.java public class BankDemo { public static void main(String [] args) { CheckingAccount c = new CheckingAccount(101); System.out.println("Depositing $500..."); c.deposit(500.00); try { System.out.println("\nWithdrawing $100..."); c.withdraw(100.00); System.out.println("\nWithdrawing $600..."); c.withdraw(600.00); } catch (InsufficientFundsException e) { System.out.println("Sorry, but you are short $" + e.getAmount()); e.printStackTrace(); } } } |
کد برنامه ی BankDemo را کامپایل و اجرا کنید تا نتیجه ی زیر را مشاهده کنید:
1 2 3 4 5 6 7 8 9 | Depositing $500... Withdrawing $100... Withdrawing $600... Sorry, but you are short $200.0 InsufficientFundsException at CheckingAccount.withdraw(CheckingAccount.java:25) at BankDemo.main(BankDemo.java:13) |
در جاوا، می توان دو دسته اشکالات و خطاها را تعریف کرد:
مثال : NullPointerException، ArrayIndexOutOfBoundsException، ClassCastException
مثال : IllegalArgumentException, IllegalStateException
مدیریت خطاها همیشه یکی از شاخص های یک زبان برنامه نویسی برتر می باشد. جاوا به عنوان محبوب ترین زبان برنامه نویسی دنیا، ساز کار مناسبی را برای مدیریت خطاها ارائه می دهد که ما در بررسی مباحث چگونگی کار با exception در جاوا آن ها را ارائه کردیم.