سلام! در آخرین سخنرانی با چنین جنبه ای از زبان جاوا به عنوان استثنا آشنا شدیم و نمونه هایی از کار با آنها را دیدیم. امروز نگاهی عمیق تر به ساختار آنها خواهیم داشت و همچنین یاد می گیریم که چگونه استثناهای خود را بنویسیم :)
انواع استثنائات
همانطور که گفتیم در جاوا کلاس های استثنای زیادی وجود دارد، تقریباً 400! اما همه آنها به گروه ها تقسیم می شوند، بنابراین به خاطر سپردن آنها بسیار آسان است. در اینجا به نظر می رسد: همه استثناها یک کلاس اجداد مشترک دارندThrowable
. دو گروه بزرگ از آن می آیند - استثناها (Exception) و خطاها (Error). خطا یک خطای مهم در هنگام اجرای برنامه است که با عملکرد ماشین مجازی جاوا مرتبط است. در بیشتر موارد، Error نیازی به رسیدگی ندارد، زیرا نشان دهنده برخی نقص های جدی در کد است. معروف ترین خطاها: StackOverflowError
- برای مثال زمانی که یک متد به طور بی پایان خود را فراخوانی می کند، رخ می دهد و OutOfMemoryError
- زمانی رخ می دهد که حافظه کافی برای ایجاد اشیاء جدید وجود نداشته باشد. همانطور که می بینید، در این شرایط، اغلب چیز خاصی برای پردازش وجود ندارد - کد به سادگی اشتباه نوشته شده است و باید دوباره انجام شود. استثناها در واقع استثنا هستند: یک موقعیت استثنایی و برنامه ریزی نشده که در حین اجرای برنامه رخ داده است. این خطاها به اندازه Error جدی نیستند، اما توجه ما را می طلبند. همه استثناها به 2 نوع تقسیم می شوند - علامت زده شده ( بررسی شده ) و بدون علامت ( چک نشده ). همه استثناهای بررسی شده از Exception
. "قابل تایید" به چه معناست؟ ما به طور جزئی در سخنرانی گذشته به این موضوع اشاره کردیم : "...کامپایلر جاوا در مورد رایج ترین استثناها می داند و می داند که در چه موقعیت هایی می توانند رخ دهند." به عنوان مثال، او می داند که اگر یک برنامه نویس داده ها را از یک فایل به صورت کد بخواند، به راحتی ممکن است این وضعیت ایجاد شود که فایل وجود ندارد. و بسیاری از چنین موقعیت هایی وجود دارد که او می تواند از قبل پیش بینی کند. بنابراین، کامپایلر کد ما را از قبل برای استثناهای احتمالی بررسی می کند. اگر آنها را پیدا کند، تا زمانی که آنها را پردازش نکنیم یا به بالای صفحه ارسال کنیم، کد را کامپایل نمی کند. نوع دوم استثناء "بدون علامت" است. آنها از کلاس می آیند RuntimeException
. تفاوت آنها با آزمایش شده چیست؟ به نظر میرسد که دستهای از کلاسهای مختلف نیز وجود دارند که از RuntimeException
استثنائات خاص زمان اجرا آمده و توصیف میکنند. تفاوت این است که کامپایلر انتظار این خطاها را ندارد. به نظر میرسد او میگوید: «در زمان نوشتن کد، چیز مشکوکی نیافتم، اما در حین کار مشکلی پیش آمد. ظاهراً در کد خطا وجود دارد!» و در واقع همینطور است. استثناهای بدون علامت اغلب نتیجه خطاهای برنامه نویس هستند. و کامپایلر به وضوح قادر به ارائه تمام موقعیت های نادرست ممکن نیست که افراد می توانند با دست خود ایجاد کنند :) بنابراین، مدیریت چنین استثنائاتی را در کد ما بررسی نمی کند. قبلاً با چندین استثناء بدون علامت روبرو شده اید:
ArithmeticException
زمانی اتفاق می افتد که بر صفر تقسیم شودArrayIndexOutOfBoundsException
هنگام تلاش برای دسترسی به سلولی خارج از آرایه رخ می دهد.
چگونه استثنا خود را پرتاب کنیم
البته، سازندگان جاوا قادر به ارائه تمام موقعیت های استثنایی که ممکن است در برنامه ها ایجاد شود، نیستند. برنامه های زیادی در جهان وجود دارد و آنها بسیار متفاوت هستند. اما اشکالی ندارد، زیرا در صورت لزوم می توانید استثناهای خود را ایجاد کنید. این کار خیلی راحت انجام می شود. تنها کاری که باید انجام دهید این است که کلاس خود را ایجاد کنید. نام آن باید با "Exception" ختم شود. کامپایلر به این نیاز ندارد، اما برنامه نویسانی که کد شما را می خوانند بلافاصله متوجه می شوند که این یک کلاس استثنا است. علاوه بر این، باید مشخص کنید که کلاس از کلاس آمده استException
. این از قبل برای کامپایلر و عملکرد صحیح ضروری است. به عنوان مثال، ما یک کلاس Dog داریم - Dog
. ما می توانیم سگ را با استفاده از walk()
. اما قبل از آن، باید بررسی کنیم که آیا حیوان خانگی ما یقه، افسار و پوزه بسته است یا خیر. اگر هرکدام از این موارد وجود نداشته باشد، ما استثنای خود را ایجاد می کنیم DogIsNotReadyException
. کد آن به شکل زیر خواهد بود:
public class DogIsNotReadyException extends Exception {
public DogIsNotReadyException(String message) {
super(message);
}
}
برای نشان دادن اینکه یک کلاس یک استثنا است، باید Exception را بعد از نام کلاس بنویسید: این به این معنی است که "کلاس از کلاس Exception مشتق شده است." در سازنده، ما به سادگی سازنده کلاس را Exception
با یک خط فراخوانی می کنیم message
- پیامی از سیستم که خطای رخ داده را توصیف می کند، به کاربر نمایش می دهد. این چیزی است که در کد کلاس ما به نظر می رسد:
public class Dog {
String name;
boolean isCollarPutOn;
boolean isLeashPutOn;
boolean isMuzzlePutOn;
public Dog(String name) {
this.name = name;
}
public static void main(String[] args) {
}
public void putCollar() {
System.out.println("The collar is on!");
this.isCollarPutOn = true;
}
public void putLeash() {
System.out.println("The leash is on!");
this.isLeashPutOn = true;
}
public void putMuzzle() {
System.out.println("The muzzle is on!");
this.isMuzzlePutOn = true;
}
public void walk() throws DogIsNotReadyException {
System.out.println("Let's go for a walk!");
if (isCollarPutOn && isLeashPutOn && isMuzzlePutOn) {
System.out.println("Hurrah, let's go for a walk!" + name + " I am glad!");
} else {
throw new DogIsNotReadyException("Dog " + name + "not ready for a walk! Check your gear!");
}
}
}
اکنون روش ما walk()
یک استثنا می اندازد DogIsNotReadyException
. این کار با استفاده از کلمه کلیدی انجام می شود throw
. همانطور که قبلاً گفتیم، استثنا یک شی است. بنابراین، در روش ما، هنگامی که یک موقعیت استثنایی رخ می دهد - چیزی در سگ وجود ندارد - یک شی کلاس جدید ایجاد می کنیم DogIsNotReadyException
و با استفاده از کلمه آن را به برنامه می اندازیم throw
. پرتاب ها را به امضای متد walk()
اضافه می کنیم DogIsNotReadyException
. به عبارت دیگر، کامپایلر اکنون آگاه است که فراخوانی متد walk()
ممکن است منجر به استثنا شود. بنابراین هنگامی که ما این را در جایی از برنامه فراخوانی می کنیم، استثنا باید رسیدگی شود. بیایید سعی کنیم این کار را در روش انجام دهیم main()
:
public static void main(String[] args) {
Dog dog = new Dog("Mukhtar");
dog.putCollar();
dog.putMuzzle();
dog.walk();//Unhandled exception: DogIsNotReadyException
}
کامپایل نمی کند، استثنا رسیدگی نمی شود! بیایید کد خود را در یک بلوک بپیچیم try-catch
تا استثنا را مدیریت کنیم:
public static void main(String[] args) {
Dog dog = new Dog("Mukhtar");
dog.putCollar();
dog.putMuzzle();
try {
dog.walk();
} catch (DogIsNotReadyException e) {
System.out.println(e.getMessage());
System.out.println("Checking equipment! Is the collar on?" + dog.isCollarPutOn + "\r\n Is the leash on?"
+ dog.isLeashPutOn + "\r\n Are you wearing a muzzle?" + dog.isMuzzlePutOn);
}
}
حالا به خروجی کنسول نگاه می کنیم:
Ошейник надет!
Намордник надет!
Собираемся на прогулку!
Собака Мухтар не готова к прогулке! Проверьте экипировку!
Проверяем снаряжение! Ошейник надет? true
Поводок надет? false
Намордник надет? true
ببینید خروجی کنسول چقدر آموزنده تر شده است! هر مرحله ای که در برنامه اتفاق افتاد را می بینیم. ما می بینیم که خطا کجا رخ داده است و بلافاصله متوجه می شویم که سگ ما دقیقاً چه چیزی را از دست داده است :) به این ترتیب استثناهای خود را ایجاد می کنیم. همانطور که می بینید، هیچ چیز پیچیده ای نیست. و اگرچه توسعه دهندگان جاوا زحمت اضافه کردن یک استثنای خاص به زبان خود را برای سگ های نادرست به خود ندادند، ما نظارت آنها را اصلاح کردیم :)
GO TO FULL VERSION