JavaRush /وبلاگ جاوا /Random-FA /استثنا در جاوا
Roman
مرحله

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

در گروه منتشر شد
وقتی با موضوع "استثناها" روبرو شدم، سؤالات زیادی مطرح شد که مجبور شدم در گوشه های مختلف اینترنت به دنبال پاسخ آنها بگردم تا با جزئیات بفهمم که همه اینها چگونه کار می کند. در نتیجه، من توضیحات خود را جمع آوری کرده ام، که ممکن است برای مبتدیانی که به تازگی با این پدیده مواجه شده اند قابل درک تر باشد. استثناها در جاوا - 1در کامپیوترها، وقفه یک سیگنال ورودی به پردازنده است مبنی بر اینکه رویدادی در حال رخ دادن است که نیاز به پاسخ فوری دارد. سیگنال وقفه به پردازنده نیاز دارد تا برنامه در حال اجرا را متوقف کند تا کمی دیرتر ادامه یابد، یعنی کامپیوتر باید تمام اطلاعات مرتبط با اجرای برنامه را به خاطر بسپارد. چنین وقفه هایی موقتی هستند، اگر کشنده نباشند. چنین وقفه هایی می تواند به دلیل کد برنامه یا برخی از عملکردهای سخت افزاری ایجاد شود (به عنوان مثال، فشار دادن ساده کلیدهای روی صفحه کلید، مثلاً تایمرها، برای خاموش کردن خودکار رایانه). تعداد وقفه ها به تعداد معینی محدود می شود که در تولید یک پردازنده خاص تعبیه شده است ، یعنی "کانال های" ارتباطی ویژه ای برای این کار اختصاص داده شده است که به شما امکان می دهد با دور زدن سایر فرآیندها به پردازنده دسترسی پیدا کنید. همچنین هنگامی که خطایی در کد برنامه در حال اجرا رخ می دهد (مثلاً اگر تقسیم بر صفر رخ دهد) وقفه ها به طور خودکار ایجاد می شوند. چنین وقفه هایی به طور سنتی تله یا استثنا نامیده می شوند . در چنین مواردی مرسوم است که می گویند: «استثنا پرتاب شد»، یعنی یک استثنا ایجاد شد یا یک استثنا پرتاب شد (پرتاب شد)، یعنی درخواست وقفه .با این سوال که "چه باید کرد؟" به پردازنده ارسال می شود. در این لحظه، پردازنده از کار می ایستد و نقطه ای را که در آن متوقف می شود، یا بهتر است بگوییم خوشه سلول بعدی را به یاد می آورد، اطلاعاتی که باید از آن اجرا شود. کل زنجیره دستورالعمل های اجرا شده و اجرا نشده به خاطر سپرده می شود. پس از آن، پردازنده دستورالعمل ها را از حافظه می خواند تا در صورت بروز چنین خطایی اقدام کند. مطابق با این دستورالعمل، می تواند مقادیر جدیدی را در خوشه های خاص وارد کند، زنجیره ای از اقدامات یا یک چرخه جدید (به عنوان مثال، یک چرخه بازگشت یا حلقه) و غیره اضافه کند، یعنی بسته به خطای که قبلا گذاشته شده است. دستورالعمل های down اجرا می شوند. خود سیستم کامپیوتری دارای وقفه‌های خودکار بسیاری است که پس از مدت زمان مشخصی فعال می‌شوند، به عنوان مثال، برای کنترل فرآیندهای در حال اجرا در رایانه یا اجرای آلارم‌های تنظیم‌شده، جمع‌آوری سیگنال‌های خارجی ورودی و مبدل‌های مختلف داده. شایان ذکر است که تعداد زیادی وقفه به دلایلی می توانند سیستم را کاملاً "آویزان" کنند. یک خطا در کد برنامه به طور خودکار باعث وقفه در پردازنده می شود که سعی می کند مطابق دستورالعمل های تعیین شده پردازش کند. اما همه وقفه‌ها برای مدیریت آنها طراحی نشده‌اند، یا ممکن است رویه‌ای ایجاد کند که مناسب ما نباشد، به عنوان مثال، به سادگی برنامه را خراب می‌کند. بنابراین، در برنامه نویسی، این امکان وجود دارد که وقفه خود را برای بخش خاصی از کد سازماندهی کنید که برنامه نویس به طور بالقوه احتمال خطا را در آن می بیند. در این صورت، خطا در داخل برنامه پردازش می شود و برای دستورالعمل های پردازش با پردازنده تماس نمی گیرد. تعریف چنین بلوک هایی با ایجاد یک Object "Exception" سازماندهی می شود . این شی به طور خودکار در بلوک ایجاد می شود try-catch. بلوک >tryبرای وجود خطا بررسی می شود و در صورت وجود خطا، برنامه به بلوک می رود catch، جایی که اقداماتی برای جلوگیری یا سطح خطا انجام می شود. به عنوان مثال، اگر اعداد را از صفحه کلید وارد کنیم ، که باید متعاقباً اضافه و تفریق شوند، با وارد کردن حروف از صفحه کلید، جمع آنها با Numbers غیرممکن می شود (اجازه دهید مجموع این دو متغیر را با حرف S نشان دهیم). بنابراین، به عنوان یک تیم، tryباید بررسی کنیم که آیا عدد A حاوی اعداد را می توان به عدد B حاوی حروف (یعنی S = A + B) اضافه کرد یا خیر، و اگر این امکان پذیر نیست و غیرممکن است، پس مشخص است. باید اقداماتی انجام شود تا Errors It NOT اتفاق بیفتد و یک وقفه جدید با سؤال "چه باید کرد؟" به پردازنده پرواز نکند. در صورت عدم وجود استثنا در برنامه، اجرای آن توسط پردازنده قطع می شود. اگر یک Exception وجود داشته باشد، هنگامی که توسط دستور "گیر" می شود try، کنترل به دستور منتقل می شود catch، که می تواند یک راه حل جایگزین را تنظیم کند، به عنوان مثال، ما این دو عدد را اضافه نمی کنیم، بلکه S = A را تنظیم می کنیم.
int a = 4;
String b = “hello”;
int S = 0;
 try {
   S = a + b;
   int r = 1;
 } catch (Exception igogo1) {
   S = a;
 }
 return S;
/* رشته "int r = 1;" اجرا نمی شود زیرا خطایی رخ داده است و برنامه به طور مستقیم کار را به کنترل کننده استثنا هدایت می کند (catch block*/ بنابراین، وجود Exceptions فرصتی برای حل مشکل در برنامه بدون پرتاب آن در سطح پردازنده است. شی "Exception" که به صورت خودکار در بلوک tryهنگام شناسایی خطا ایجاد می شود، حاوی مقدار نوع خطا است. بیایید آن را "OurException" بنامیم - برای مورد خاص ما با توضیح خطای خاص ما. سازندگان زبان جاوا از قبل لیست مشخصی از خطاهای معمولی و گزینه های معمولی برای تصحیح آنها ایجاد کرده اند، یعنی در جاوا یک کتابخانه خاص از Exception ها وجود دارد که می توانیم برای رسیدگی به خطای رخ داده به آن مراجعه کنیم. کد پردازش را خودمان ننویسیم و بنابراین به احتمال زیاد OurException قبلاً کسی توضیح داده شده است، بنابراین ما فقط باید نام کدام یک از این استثناها را در برنامه خود وارد کنیم تا بتوانیم کدهایی را که ممکن است به طور بالقوه خرابی رخ دهد، وارد کنیم. اگر اشتباه کنیم و یک Exception نادرست را از کتابخانه انتخاب کنیم ، کنترل کننده آن را "گرفته" نمی کند، خطا راه حلی در برنامه پیدا نمی کند و درخواست به پردازنده ارسال می شود. اما برای تنبل ها راهی وجود دارد. اگر نام استثنایی را که از کتابخانه نیاز داریم ندانیم، می‌توانیم مانند مثالی که در بالا توضیح داده شد، یک مورد کلی را با نام " Exception " بگیریم. این استثنا قادر به مدیریت هر نوع خطایی است، اما قادر به ارائه اطلاعات خاصی در مورد حادثه ای نیست که بتوانیم آن را ثبت کنیم. کتابخانه Exception های قبلاً نوشته شده از Exception های علامت دار و بدون علامت تشکیل شده است . موارد قابل بررسی آنهایی هستند که بدون وقفه در کار برنامه قابل اصلاح هستند، یعنی اگر بخواهیم فایلی را در پوشه ای که در آن وجود ندارد باز کنیم، سیستم به ما اطلاع می دهد، می توانیم فایل را رها کنیم. وارد پوشه مورد نظر شده و برنامه را ادامه دهید. یعنی در واقع یک درخواست وقفه برای پردازنده ارسال شد ، اما بدون این سوال: "به دنبال این باشید که برای این مشکل چه کاری انجام دهید؟!؟!" ما یک وقفه را ارسال کردیم که خودمان آن را شناسایی کردیم با یک دستورالعمل آماده که پردازنده آن را پردازش کرد و به اجرای برنامه ادامه داد. بدون علامت خطاهایی هستند که قابل اصلاح نیستند و برنامه قبل از اتمام بسته می شود، یعنی یک درخواست وقفه برای پردازنده ارسال می شود.، که در هر صورت باعث وقفه در اجرای برنامه می شود. تنها نکته در نوشتن چنین استثناهایی در برنامه این است که به کاربر اجازه دهیم بفهمد چه اتفاقی افتاده است، زیرا با دریافت این وقفه، می توانیم یک پیام اطلاعاتی را روی صفحه نمایش دهیم که به دلیل آن برنامه از کار افتاده است. دومین دلیل برای گرفتن چنین وقفه هایی، امکان ثبت آنها در گزارش ها برای تجزیه و تحلیل بعدی است (شما هک شده اید، اما حداقل می دانید کجا). پیامد وجود چنین کتابخانه‌هایی نیاز به یادآوری گنجاندن آنهاست. (لیستی از Exception های علامت دار و بدون علامت با کتابخانه ها را می توانید پیدا کنید، به عنوان مثال، در اینجا ) اگر دقیقاً نمی دانیم کدام کتابخانه را باید اضافه کنیم یا چندین گزینه خطا وجود دارد، می توانیم catchاستثناهای مورد نیاز را در چندین لیست لیست کنیم. خود سیستم اگر در لیست باشد، کنترل کننده صحیح را انتخاب می کند. به جای یک استثنا خاص، می‌توانید یک « استثنا » کلی بنویسید که اگر در بلوک‌های قبلی پردازش نشده باشد، می‌تواند هر نوع استثنا را مدیریت کند.
int a = 4;
String b = “hello”;
int S = 0;
 try {
   S = a + b;
   int r = 1;
 }
catch(NullPointerException blabla2) {
   System.out.println("Exception handling code for the NullPointerException.");
 }
catch (ArithmeticException ex1) {
   S = a;
 }
catch(Exception uups1) {
   System.out.println("Exception occured");
 }
 return S;
اگر بلوکی وجود داشته باشد، tryیک استثنا به طور خودکار ایجاد می شود. اگر در یک نقطه از زمان نیاز به اعمال یک Exception داشته باشیم ، از دستور استفاده می شود throw. یعنی ما به طور مستقل یک شی ایجاد می کنیم new throw... پس از آن، برنامه کار خود را متوقف می کند، یک درخواست وقفه به پردازنده ارسال می کند و به بخش برنامه منتقل می شود catch، از آنجا سعی می کند دستورالعمل هایی را برای اقدامات بعدی دریافت کند. با ایجاد دستی یک Exception ، می توانیم نوع خاص آن را از کتابخانه مشخص کنیم:

throw new ArithmeticException("Access denied - You must be at least 18 years old.");
سپس کنترل کننده یک بلوک را catchبا این استثنای خاص جستجو می کند - جستجو در سراسر برنامه، از همه طرف catch. پس از throwدستور Exception handling، همه کدهای برنامه باقیمانده اجرا نمی شوند، به جز کدهایی که در بلوک هستند catch. اگر کنترل کننده در برنامه یافت نشد، از پردازنده این سوال پرسیده می شود: "خودت تصمیم بگیر چه کار کنی" و برنامه را قطع می کند. تماس ... هم در داخل و هم در خارج از بلوک (در هر نقطه از برنامه) new throwقابل انجام است.>try
try {
   /* функция or действие, в котором есть сомнения. То есть: «попробуй выполнить это, а если не получится, а, если не получится, запускай режим исключения» */
   throw new CallForException(); /* Назначаем исключение, которое будет работать в случае наличия ошибки в функции, описанной выше. Здесь исключение «CallForException» - берется из библиотеки существующих исключений */
} catch (CallForException ee1) {
   /* Корректируем ошибку, чтобы программа не «отвалилась» or выводим сообщение об ошибке or что-то ещё */
} finally {
   /* этот блок работает всегда независимо от того была ошибка or нет. А если была, то сработало ли решение в catch or нет */
   /* часто используется для подчистки хвостов, например, для закрытия запущенного file or базы данных */
   /* в ряде случаев блок catch вообще может быть опущен и оставлен только блок finally и наоборот finally может быть опущен и оставлен только catch */
   /* Не допускается использование этого блока в ряде случаев, например, когда функция System.exit() запущена or другие системные Исключения, типа «отключение электроэнергии» и т.п. */
}

اطلاع رسانی استثنائات

روش هایی که قبلا توسط شخصی نوشته شده است ممکن است شامل پرتاب استثناها باشد. برنامه نویسی که کد را نوشت، فقط برای حفظ امنیت، به برنامه نویسان بعدی هشدار داد که ممکن است در روشی که نوشته است خطایی رخ دهد. بنابراین، برای مثال، روش ایجاد فایل توضیح داده شده در زیر تصریح می کند که هنگام ایجاد یک فایل ممکن است خطایی رخ دهد (هیچ فایلی در مسیر داده شده وجود ندارد)، به این معنی که یک کنترل کننده خطا مورد نیاز است:
public void createFile(String path, String text) throws IOException {
    FileWriter writer = new FileWriter(path, true);
    writer.write(text);
    writer.close();
}
اما در عین حال خود هندلری وجود ندارد، به این معنی که اکنون نمی توانیم به سادگی متد نوشته شده را در برنامه خود در حالت عادی فراخوانی کنیم. اکنون باید یک کنترل کننده خطا بنویسیم و این متد را در بلوک فراخوانی کنیم try:
String filePath = "hello.txt";
String text = "Hello World";

try {
    createFile(filePath, text);
} catch (IOException ex) {
    System.err.println("Error creating file: " + ex);
}

استثناهای بومی

اگر کتابخانه های موجود برای ما کافی نیستند، می توان استثناهای خود را برای رسیدگی به برخی خطاها بنویسید. برای انجام این کار، ما به سادگی یک کلاس ایجاد می کنیم که از کلاس Exception به ارث می رسد
public class StudentNotFoundException extends Exception {

    public StudentNotFoundException (String message) {
        super(message);
    }
}
هنگام ایجاد استثناهای خود دو قانون وجود دارد که باید در نظر داشته باشید:
  1. نام کلاس ما باید با "Exception" ختم شود
  2. کلاس باید شامل سازنده ای با متغیر رشته ای باشد که جزئیات مسئله Exception را توصیف می کند. در سازنده، ابر سازنده فراخوانی می شود و یک پیام ارسال می شود.
مثالی از استفاده از استثنای تولید شده:
public class StudentManager {
    public Student find(String studentID) throws StudentNotFoundException {
        if (studentID.equals("123456")) {
            return new Student();
        } else {
            throw new StudentNotFoundException(
                "Could not find student with ID " + studentID);
        }
    }
}
ما این استثنا را با کد زیر می گیریم:
public class StudentTest {
    public static void main(String[] args) {
        StudentManager manager = new StudentManager();
         try {
            Student student = manager.find("0000001");
        } catch (StudentNotFoundException ex) {
            System.err.print(ex);
        }
    }
}
نتیجه اجرای برنامه این خواهد بود: StudentNotFoundException: دانش آموز با شناسه 0000001 یافت نشد

چرا باید استثناها را بنویسید؟

در سال 1996، موشک آریان 5 به دلیل تبدیل نادرست یک متغیر شناور به یک متغیر صحیح سقوط کرد. هیچ استثنا یا کنترل کننده ای برای این وضعیت وجود نداشت. اگر هنگام دانلود فایل اتصال به اینترنت قطع شد، وجود Exception به شما امکان می دهد پس از بازیابی اتصال، دانلود را ادامه دهید. اگر استثنا وجود نداشته باشد، دانلود باید دوباره شروع شود.

منابع:

نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION