پارسا کاویان پور
پارسا کاویان پور
خواندن ۳ دقیقه·۳ سال پیش

انواع استثناء در جاوا

سلسله مراتب استثنا در جاوا
سلسله مراتب استثنا در جاوا

استثناء چیست ؟

استثناء دلالت بر وجود مشکلی دارد که در زمان اجرای برنامه رخ میدهد. نام استثناء از این حقیقت بر امده است که اگر چه مشکل میتواند همیشه رخ دهد اما استثناء بندرت و در شرایطی خاص رخ میدهد.اگر قاعده ای بر این اصل استوار باشد که عبارتی به طرز صحیح اجرا میشود اما رویدادی میتواند موجب رخ دادن مشکلی گردد پس استثنائی در این قاعده وجود دارد.


چرا باید استثناء را مدیریت کنیم؟

به کمک مدیریت استثناء میتوانیم از قطع جریان برنامه توسط استثنای رخ داده جلوگیری کرده و به اجرا ادامه دهیم . در مواردی که امکان اجرای برنامه وجود ندارد نیز با پیغام مناسب کاربر را اگاه کنیم.


سلسله مراتب استثناء در جاوا :

تمام کلاس های استثناء در جاوا از کلاس Exception ارث بری دارند . کلاس های Error و زیر کلاس های ان مانند ThreadDeath, OutOfMemoryException,VirtualMachineError و... نشاندهنده ی حالات غیر عادی هستند که میتوانند در سطح ماشین مجازی جاوا (JVM) رخ دهند . این خطاها به ندرت اتفاق می افتند و توسط مکانیزم مدیریت استثناء نمیتوان آنها را مدیریت کرد .


استثناء های چک نشده در برابر چک شده:

تمایز مابین این دو از اهمیت ویژه ای برخوردار است چرا که رفتار کامپایلر جاوا با این دو متفاوت است. تمام کلاس هایی که از RuntimeExceptionارث بری میکنند چک نشده و تمام کلاس هایی که از Exception ارث بری میکنند چک شده(Checked) هستند

لازم به ذکر است زیر کلاس های Error همگی چک نشده هستند(Unchecked)

در استثناء های چک شده کامپایلر باید اطمینان یابد که استثناء چک شده در بلوک catch گرفتار میشود .

با استفاده از کلمه ی کلیدی throws در هنگام تعریف متد, استثناء های چک شده ای که ممکن است متد سبب انها شود اعلام میشوند :

public class ExceptionExample{ public void method1() throws Exception{ } public void method2(){ try{ method1(); } catch(Exception e){ // handle } } }


رویکرد جاوا در استثناء های چک شده برنامه نویس را مجبور میکند تا در مورد مشکلی که ممکن است رخ دهد فکری کند

اما در استثناء های چک نشده کامپایلر چنین فرایندی را طی نمیکند چرا که عموما میتوان با کدنویسی مناسب و صحیح مانع رخ دادن استثناء های چک نشده شد

برای مثال هنگام تقسیم بر صفر میتوانیم قبل از تقسیم اطمینان یابیم که مقسوم علیه صفر نیست . و در این صورت استثنای ArithmeticException به راه نمی افتد .

همچنین در استثناء های چک نشده احتیاجی به استفاده از کلمه کلیدی throws در هنگام تعریف متد نیست:


public class ExceptionExample{
public double divide(int i1,int i2){
if(i2!=0) return i1/i2;
}
}


اما در حالت عادی اگر صفر میدادیم و متد را به صورت بالا ننوشته بودیم گرفتار استثنا میشدیم:


public class ExceptionExample{
public double divide(int i1,int i2){
return i1/i2;
}
}


بررسی بلوک finally:

برنامه ها بطور مکرر تقاضای دریافت و رها سازی منابع را دارند . برای مثال برنامه ای که فایلی از دیسک میخواند ابتدا تقاضای بازکردن فایل را بعمل می اورد سپس در صورت موافقت برنامه محتویات را خواهد خواند. به طور کلی سیستم عامل از دستکاری مکرر چندین برنامه در یک فایل و بصورت همزمان جلوگیری میکند از این رو زمانیکه پردازش پایان می یابد فایل باستی توسط برنامه بسته شود (منبع ازاد شود)

فرض کنید در حین خواندن فایل استثنایی رخ داده است. برای جلوگیری از فقدان منابع و بسته نشدن فایل, باید به نحوی بتوانیم منبع اشغال شده را ازاد کنیم. اینجاست که finally به ما کمک میکند.

این بلوک اختیاری ست و بعد از اخرین بلوک catch قرار میگیرد (میتوان بدون وجود catch بلافاصله بعد از try این بلوک را قرار داد)

همیشه پس از اجرای بلوک های catch بلوک finally اجرا میگردد

شاید بپرسید چرا در همان بلوک catch منابع را ازاد نکننیم؟ بخاطر اینکه اجرای catch وابسته به نوع استثنای رخ داده است و اگر فرضا ماIOException را هندل کردیم و NullponterException رخ داده است دیگر catch ای که حاوی IOException است اجرا نمیشود و از این رو منبع ازاد نمیگردد:

public void method{ Scanner in = null; try{ in = new Scanner(System.in); }catch(IOException e){ System.out.println(e.getMessage()); } finally{ in.close(); } }


در نسخه ی java 7 به بعد میتوان از try-with-resources استفاده کرد . در این صورت دیگر نیازی به استفاده از finally نیست . کد بالا را به صورت زیر بازنویسی میکنیم:


try(Scanner in = new Scaner(System.in)){
// use the Scanner here
} catch(IOException e){
// catch Exception that occur while using the resource
System.out.println(e.getMessage());
}

نکته : بدون catch نیز میتوانستیم از try-with-resources صرفا برای ازاد سازی خودکار منابع استفاده کنیم.

try(Scanner in =new Scanner(System.in)){
// use the Scanner here
}



سایر مطالب مرتبط:

کلاس Optional در جاوا


منابع :

https://docs.oracle.com/en/java/javase/17/

Java how to program? 8th edition


exceptiontrycatchfinallyruntimeexceptionioexception
شاید از این پست‌ها خوشتان بیاید