استثنا ها و خطاها در جاوا

ناصر نادری | 1393/11/12


بنام خدا . در آخرین جلسه از جلسات بخش مقدماتی جاوا در خدمت دوستان هستیم به مبحث استثنا ها (Exceptions)و خطاها (Error).

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

استثنا ها به 3 دسته اصلی تقسیم میشن :

Checked Exception : استثناهایی که در تعامل کاربر با برنامه بوجو میاد و  معمولا قابل پیش بینی توسط برنامه نویس نیست .  بطور مثال یک کاربر فایلی رو برای بازکردن انتخاب میکنه  که وجود نداره .

Runtime Exception : انواع خطاهایی که در زمان اجرا  بوجو میان و برنامه نویس مسئول ایجاد این نوع استثنا ها ست.

Errors : این بخش رو در واقع نمی تونیم استثنا بنامیم . این ها در واقع همون خطاها هستن مثل بروز stack overflow.

کلاس java.lang.Exception که زیر کلاسی از کلاس Throwable هست برای مدیریت استثناها کاربرد داره و کلاس Error که اونهم  از کلاس Throwable گرفته میشه  برای مدیریت خطاها استفاده میشه . 

خطاهای شدید معمولا توسط یک برنامه جاوا به دام نمیفتن . یعنی نمیتونیم اونهارو کنترل کنیم و از حوزه خطا خارج بشیم و به برنامه ادامه بدیم .

لیست زیر متدهای مهم در کلاس Throwable رو نمایش میده

متد ها با توضیحات
public String getMessage() پیغامی حاوی جزیات مربوط به استثنا رخ داده رو برمیگردونه.
public Throwable getCause() دلیل رخ داد استثنا رو  برمیگردونه.
public void printStackTrace() جریان ایجاد خطا در حافظه استک رو. چاپ میکنه.
public StackTraceElement [] getStackTrace() بازگرداندن یک ارایه شامل تمام المالنهای استک . خانه 0 نشاندهنده بالا ترین نقطه استک حاوی خطا میباشد, .
public Throwable fillInStackTrace() پشته ردیابی خطا  آبجکت جاری مدیریت استثنا رو با پشته جاری ردیابی خطا پر میکنه  .

ساده ترین شکل استفاده از بلام مدیریت استثنا ها رو میبینیم :


 try
{
    //کدی که ازش محافظت میکنیم
}catch(ExceptionName e1)
{
    //کدی که در هنگام بروز استثنا اجرا میشه
} 

مثال زیر کمی قضیه رو روشن تر می کنه  :


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");//خارج شدن کنترل از 
بلوک استثنا و ادامه برنامه
  }
}

نتیجه اجرای برنامه :


Exception thrown 
:java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block

میتونیم چند تا بلاک  مدیریت استثنا داشته باشیم . این کار برای این هست که امکان داره که یک استثنا به هردلیلی اتفاق بیفته . برنامه نویس پیش بینی میکنه که مثلا احتمال داره دسترسی غیر مجاز به عناصر ارایه اتفاق بیفته یا مثلا درسترسی به یک شی با مقدار null درنتیجه میتونه هر چنر تا که احتمال میزنه براشون استثنا تعریف کنه .


try
{
    //کدی که ازش محافظت میکنیم
}catch(ExceptionType1 e1)
{
    //کدی که اگه استثنا نوع اول اتفاق بیفته اجرا میشه
}catch(ExceptionType2 e2)
{
     //کدی که اگه استثنا نوع دوم  اتفاق بیفته اجرا میشه
}catch(ExceptionType3 e3)
{
    //کدی که اگه استثنا نوع  سوم اتفاق بیفته اجرا میشه
}

به مثال زیر توجه کنید :


try
{
    file = new FileInputStream(fileName);// چون از فایل استفاده 
میکنیم احتمال داره خطای مربوط به فایل اتفاق بیفته که خودش انواع مختلف داره
    x = (byte) file.read();
}catch(IOException i)// کنترل خطای مربوط به ورودی و خروجی
{
    i.printStackTrace();
    return -1;
}catch(FileNotFoundException f) //کنترل خطای مربوط به پیدا نکردن فایل
{
    f.printStackTrace();
    return -1;
}

کلمه کلیدی Throw , Throws :

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


import java.io.*;
public class className
{
   public void deposit(double amount) throws RemoteException
  {
        // بدنه متد
        throw new RemoteException();// ایجاد 
یک استثنای  جدید برای کنترل جریان متد
   }
   //Remainder of class definition
}

در مثال زیر از چند استثنا  احتمالی در نتیجه اجرای متد استفاده میکنیم :


import java.io.*;
public class className
{//احتمال رخ داد این خطاها لیست میشه و با علامت کاما از هم جدا میشن
    public void withdraw(double amount) throws RemoteException, 
InsufficientFundsException
    {
        // بدنه متد
    }
    //باقیمانده کد کلاس
}

بلاک finaly :

کدی که در این بلا نوشته میشه چه استثنا رخ بده و چه رخ نده اجرا خواهد شد . مثلا وقتی با فایل دارید کار میکنید چه خطا رخ بده و چه رخ نده مجبور به بستن فایل در انتهای کار هستید , پس کد بستن فایل رو تو این بخش مینویسید .


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");    
      }
    }
}

نتیجه اجرای کد بالا :


Exception thrown 
:java.lang.ArrayIndexOutOfBoundsException: 3
First element value: 6
The finally statement is executed

شما میتونید خودتون یک نوع استثنا ایجاد کنید . توی ایجاد استثنای شخصی  باید به موارد زیر توجه کنید :

- تمام استثنا ها باید یک فرزند از کلاس Throwable باید باشن

- اگه میخوایید استثنایی از نوع Checked ایجاد کنید باید اون رو از نوع  Exception ایجاد کنید

- اگه میخوایید از نوع Runtime ایجاد کنید باید از کلاس RuntimeException  ایجاد کنید

این استثنا ها بصورت کلاس پیاده سازی میشه :


class MyException extends Exception{
}

مثال زیر رو خو مطالعه کنید


//InsufficientFundsException.java این کلاس داخل این فایل ذخیره بشه
// ایجاد یک کلاس استثنا شخصی از نوع Checked
import java.io.*;

    public class InsufficientFundsException extends Exception
    {
        private double amount;
        public 
InsufficientFundsException(double amount)
        {
            this.amount = amount;
        } 
        public double getAmount()
    {
        return amount;
    }
}

از کلاس استثنا بالا استفاده میکنیم :


// 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;
     }
}

و کلاس پایین از کلاس CheckingAccount  استفاده میکنه :


// 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.java رو از خط فرمان اجرا کنید  نتیجه زیر :


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)

تا دوره بعدی یعنی شی گرایی در جاوا در پناه حق .


فایلهای ضمیمه
توجه! هیچ فایل ضمیمه ای برای این مطلب یافت نشد

نظرات شما نظر جدید