CodeGym /وبلاگ جاوا /Random-FA /استثنا در جاوا
John Squirrels
مرحله
San Francisco

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

در گروه منتشر شد
سلام! در درس امروز، در مورد استثناهای جاوا صحبت خواهیم کرد. زندگی روزمره پر از موقعیت هایی است که ما پیش بینی نمی کنیم. مثلاً صبح برای سرکار بیدار می شوید و به دنبال شارژر گوشی خود می گردید، اما هیچ جا آن را پیدا نمی کنید. برای دوش گرفتن به حمام می روید و متوجه می شوید که لوله ها یخ زده اند. سوار ماشینت میشی ولی روشن نمیشه یک انسان می تواند به راحتی با چنین شرایط پیش بینی نشده کنار بیاید. در این مقاله سعی می کنیم بفهمیم برنامه های جاوا چگونه با آنها برخورد می کنند.

استثنای جاوا چیست؟

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

چند کلمه در مورد کلمات کلیدی

مدیریت استثنا در جاوا بر اساس استفاده از کلمات کلیدی زیر در برنامه است:
  • try - یک بلوک از کد را تعریف می کند که در آن یک استثنا می تواند رخ دهد.
  • catch - یک بلوک از کد را تعریف می کند که در آن استثناها مدیریت می شوند.
  • در نهایت - یک بلوک اختیاری از کد را تعریف می کند که در صورت وجود، بدون توجه به نتایج بلوک try اجرا می شود.
این کلمات کلیدی برای ایجاد ساختارهای ویژه در کد استفاده می شوند: سعی کنید{}catch , try{}catch{}finally , try{}finally{} .
  • انداختن - برای مطرح کردن یک استثنا استفاده می شود.
  • پرتاب - در امضای متد برای هشدار دادن به اینکه متد ممکن است یک استثنا ایجاد کند استفاده می شود.
مثالی از استفاده از کلمات کلیدی در برنامه جاوا:
// This method reads a string from the keyboard

public String input() throws MyException { // Use throws to warn
// that the method may throw a MyException
      BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    String s = null;
// We use a try block to wrap code that might create an exception. In this case,
// the compiler tells us that the readLine() method in the
// BufferedReader class might throw an I/O exception
    try {
        s = reader.readLine();
// We use a catch block to wrap the code that handles an IOException
    } catch (IOException e) {
        System.out.println(e.getMessage());
// We close the read stream in the finally block
    } finally {
// An exception might occur when we close the stream if, for example, the stream was not open, so we wrap the code in a try block
        try {
            reader.close();
// Handle exceptions when closing the read stream
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    if (s.equals("")) {
// We've decided that an empty string will prevent our program from working properly. For example, we use the result of this method to call the substring(1, 2) method. Accordingly, we have to interrupt the program by using throw to generate our own MyException exception type.
        throw new MyException("The string cannot be empty!");
    }
    return s;
}

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

بیایید به یک مثال از دنیای واقعی نگاه کنیم. تصور کنید که بخشی از بزرگراه دارای یک پل کوچک با ظرفیت وزن محدود است. اگر خودرویی سنگین تر از حد پل از روی آن برود، ممکن است سقوط کند. وضعیت برای راننده، به بیان ملایم، استثنایی خواهد بود. برای جلوگیری از این امر، اداره حمل و نقل علائم هشدار دهنده را قبل از بروز هر مشکلی در جاده نصب می کند. راننده با دیدن علامت هشدار، وزن وسیله نقلیه خود را با حداکثر وزن پل مقایسه می کند. اگر وسیله نقلیه بیش از حد سنگین باشد، راننده یک مسیر فرعی را طی می کند. اداره حمل و نقل ابتدا این امکان را برای رانندگان کامیون ایجاد کرد که در صورت لزوم مسیر خود را تغییر دهند، دوم به رانندگان در مورد خطرات جاده اصلی هشدار داد و سوم به رانندگان هشدار داد که در شرایط خاصی نباید از پل استفاده شود. استثناها در جاوا - 2توانایی جلوگیری و حل و فصل موقعیت‌های استثنایی در یک برنامه که به آن اجازه می‌دهد به اجرا ادامه دهد، یکی از دلایل استفاده از استثناها در جاوا است. مکانیسم استثنا همچنین به شما این امکان را می دهد که با تأیید (بررسی) هر ورودی، از کد خود (API) در برابر استفاده نادرست محافظت کنید. حالا تصور کنید که برای یک ثانیه بخش حمل و نقل هستید. ابتدا باید مکان‌هایی را بشناسید که رانندگان در آن‌ها انتظار مشکل دارند. دوم، شما نیاز به ایجاد و نصب علائم هشدار دهنده دارید. و در نهایت، در صورت بروز مشکل در مسیر اصلی، باید مسیرهای انحرافی را ارائه دهید. در جاوا، مکانیسم استثنا به روشی مشابه کار می کند. در طول توسعه، از یک بلوک try برای ایجاد یک «موانع استثنا» در اطراف بخش‌های خطرناک کد استفاده می‌کنیم ، «مسیرهای پشتیبان» را با استفاده از یک بلوک catch {} ارائه می‌کنیم ، و کدی را می‌نویسیم که بدون توجه به آنچه در بلوک نهایی{} باید اجرا شود. . اگر نمی‌توانیم «مسیر پشتیبان» ارائه کنیم یا می‌خواهیم به کاربر حق انتخاب بدهیم، حداقل باید خطر را به او گوشزد کنیم. چرا؟ فقط خشم راننده ای را تصور کنید که بدون دیدن حتی یک علامت هشدار به پل کوچکی می رسد که نمی تواند از آن عبور کند! در برنامه نویسی، هنگام نوشتن کلاس ها و متدهای خود، ما همیشه نمی توانیم نحوه استفاده از آنها توسط توسعه دهندگان دیگر را پیش بینی کنیم. در نتیجه، نمی‌توانیم راه 100% صحیح را برای حل یک موقعیت استثنایی پیش‌بینی کنیم. با این اوصاف، هشدار دادن به دیگران در مورد احتمال موقعیت‌های استثنایی، روش خوبی است. مکانیسم استثنای جاوا به ما این امکان را می دهد که این کار را با کلمه کلیدی throws انجام دهیم - اساساً بیانیه ای است که رفتار کلی روش ما شامل پرتاب یک استثنا است. بنابراین، هر کسی که از این روش استفاده می‌کند می‌داند که باید برای مدیریت استثناها کد بنویسد.

هشدار به دیگران در مورد "مشکل"

اگر برای مدیریت استثناها در روش خود برنامه ریزی نمی کنید، اما می خواهید به دیگران هشدار دهید که ممکن است استثناهایی رخ دهد، از کلمه کلیدی throws استفاده کنید . این کلمه کلیدی در امضای متد به این معنی است که، تحت شرایط خاص، متد ممکن است یک استثنا ایجاد کند. این اخطار بخشی از رابط متد است و به کاربرانش اجازه می‌دهد منطق مدیریت استثنای خود را پیاده‌سازی کنند. پس از پرتاب ها، انواع استثناهای پرتاب شده را مشخص می کنیم. اینها معمولاً از کلاس Exception جاوا می آیند . از آنجایی که جاوا یک زبان شی گرا است، همه استثناها در جاوا شی هستند. استثناها در جاوا - 3

سلسله مراتب استثنایی

هنگامی که هنگام اجرای برنامه خطایی رخ می دهد، JVM یک شی از نوع مناسب را از سلسله مراتب استثنایی جاوا ایجاد می کند - مجموعه ای از استثناهای احتمالی که از یک اجداد مشترک نشات می گیرند - کلاس Throwable . می‌توانیم موقعیت‌های زمان اجرا استثنایی را به دو گروه تقسیم کنیم:
  1. موقعیت هایی که برنامه نمی تواند بازیابی شود و به عملکرد عادی ادامه دهد.
  2. شرایطی که بهبودی امکان پذیر است.
گروه اول شامل موقعیت هایی است که شامل یک استثنا می شود که از کلاس Error نزول می کند . اینها خطاهایی هستند که به دلیل نقص JVM، سرریز حافظه یا خرابی سیستم رخ می دهند. آنها معمولاً مشکلات جدی را نشان می دهند که توسط نرم افزار قابل رفع نیستند. در جاوا، امکان وجود چنین استثناهایی توسط کامپایلر بررسی نمی شود، بنابراین آنها را به عنوان استثناهای بدون بررسی می شناسند. این گروه شامل RuntimeExceptions نیز می شود که استثناهایی هستند که از کلاس Exception فرود می آیند و در زمان اجرا توسط JVM تولید می شوند. آنها اغلب به دلیل خطاهای برنامه نویسی ایجاد می شوند. این استثناها نیز در زمان کامپایل بررسی نمی شوند (برداشتن علامت)، بنابراین برای مدیریت آنها نیازی به نوشتن کد ندارید. گروه دوم شامل موقعیت‌های استثنایی است که می‌توان آن‌ها را هنگام نوشتن برنامه پیش‌بینی کرد (و بنابراین باید کدی را برای مدیریت آنها بنویسید). چنین استثناهایی را استثناهای بررسی شده می نامند. وقتی صحبت از استثناها می شود، بیشتر کار یک توسعه دهنده جاوا رسیدگی به چنین موقعیت هایی است.

ایجاد یک استثنا

هنگامی که یک برنامه اجرا می شود، استثناها یا توسط JVM یا به صورت دستی و با استفاده از یک دستور drop ایجاد می شوند . هنگامی که این اتفاق می افتد، یک شی استثنا در حافظه ایجاد می شود، جریان اصلی برنامه قطع می شود، و کنترل کننده استثناء JVM سعی می کند استثنا را مدیریت کند.

رسیدگی به استثنا

در جاوا، ما بلوک‌های کد ایجاد می‌کنیم که در آن نیاز به مدیریت استثنا با استفاده از ساختارهای try{}catch , try{}catch{}finally , and try{}finally{} را پیش‌بینی می‌کنیم. استثناها در جاوا - 4هنگامی که یک استثنا در یک بلوک try انداخته می شود ، JVM به دنبال یک کنترل کننده استثنای مناسب در بلوک catch بعدی می گردد . اگر یک بلوک catch دارای کنترل کننده استثنای مورد نیاز باشد، کنترل به آن منتقل می شود. در غیر این صورت، JVM به دنبال زنجیره بلوک های گیر بیشتر می شود تا زمانی که کنترل کننده مناسب پیدا شود. پس از اجرای بلوک catch ، کنترل به بلوک نهایی اختیاری منتقل می شود . اگر بلوک catch مناسب پیدا نشد، JVM برنامه را متوقف می‌کند و stack trace (پشته فعلی فراخوانی‌های متد) را پس از انجام اولین بلوک نهایی در صورت وجود، نمایش می‌دهد. نمونه ای از رسیدگی به استثنا:
public class Print {

     void print(String s) {
        if (s == null) {
            throw new NullPointerException("Exception: s is null!");
        }
        System.out.println("Inside print method: " + s);
    }

    public static void main(String[] args) {
        Print print = new Print();
        List list= Arrays.asList("first step", null, "second step");

        for (String s : list) {
            try {
                print.print(s);
            }
            catch (NullPointerException e) {
                System.out.println(e.getMessage());
                System.out.println("Exception handled. The program will continue");
            }
            finally {
                System.out.println("Inside finally block");
            }
            System.out.println("The program is running...");
            System.out.println("-----------------");
        }

    }
    }
در اینجا نتایج روش اصلی آورده شده است :
Inside print method: first step
Inside finally block
The program is running...
-----------------
Exception: s is null!
Exception handled. The program will continue
Inside finally block
The program is running...
-----------------
Inside print method: second step
Inside finally block
The program is running...
-----------------
در نهایت معمولاً برای بستن هر جریانی و آزاد کردن منابع باز/تخصیص داده شده در یک بلوک آزمایشی استفاده می‌شود. با این حال، هنگام نوشتن یک برنامه، همیشه نمی توان بسته شدن همه منابع را پیگیری کرد. برای آسان‌تر کردن زندگی ما، توسعه‌دهندگان جاوا ساختار try-with-resources را ارائه می‌کنند که به طور خودکار هر منبعی را که در یک بلوک try باز می‌شود، می‌بندد. اولین مثال ما را می توان با try-with-resources بازنویسی کرد :
public String input() throws MyException {
    String s = null;
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))){
        s = reader.readLine();
   } catch (IOException e) {
       System.out.println(e.getMessage());
   }
    if (s.equals("")) {
        throw new MyException ("The string cannot be empty!");
    }
    return s;
}
به لطف قابلیت‌های جاوا معرفی‌شده در نسخه 7، ما همچنین می‌توانیم استثناهای ناهمگن را در یک بلوک ترکیب کنیم و کد را فشرده‌تر و خواناتر کنیم. مثال:
public String input() {
    String s = null;
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
        s = reader.readLine();
        if (s.equals("")) {
            throw new MyException("The string cannot be empty!");
        }
    } catch (IOException | MyException e) {
        System.out.println(e.getMessage());
    }
    return s;
}

خط پایین

استفاده از استثناها در جاوا به شما این امکان را می‌دهد تا با ایجاد «مسیرهای پشتیبان»، برنامه‌های خود را قوی‌تر کنید، از بلوک‌های catch برای جدا کردن کد اصلی از کد مدیریت استثنا استفاده کنید، و از پرتاب‌ها برای انتقال مسئولیت رسیدگی به استثنا به هر کسی که از روش شما استفاده می‌کند استفاده کنید .
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION