آموزش برنامه نویسی جاوا

آموزش برنامه نویسی جاوا (بخش پانزدهم: معرفی Modifier ها در جاوا)

در این بخش به بررسی Modifierها در جاوا می پردازیم. اما Modifier چیست؟

Modifier ها کلمات کلیدی هستند که در ابتدای معرفی توابع (متدها) ، متغیرها و کلاس ها می آیند. یعنی نام آن ها در ابتدای متودها، متغیرها و کلاس ها می آیند و سپس نوع آن ها و… تعریف می شود.

زبان جاوا دارای Modifierهای فراوانی هستند که مورد از آنها عبارت اند از :

  • Modifierهای دسترسی
  • Modifierهای غیردسترسی

همان طور که گفته شد، برای استفاده از Modifier ها باید، نام آن ها را قبل از تعریف متغیر، متود و یا کلاس ها بیاورید. اگر یک پروژه ی جاوا در کامپایلرهای اکلیپس ، NetBeans و .. ایجاد کنید متوجه می شوید که تابع اصلی شما یعنی تابع Main از Modifier از نوع Public استفاده می کند:

public static void main(String[] args) {

// بدنه اصلی
    }

برای درک بهتر و چگونگی کارکرد و استفاده از Modifier ها، در ادامه به بررسی این دو دسته از Modifier ها می پردازیم.

Modifierهای دسترسی

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

در جاوا 4 نوع سطح دسترسی داریم:

1- قابل استفاده در همه جای برنامه:

این نوع دسترسی امکان استفاده از متغیر، متود و یا کلاس را در همه جای برنامه حتی خارج از پکیج را به جاوا می دهد. برای این که این سطح دسترسی را مشخص کنیم، از کلمه کلیدی Public استفاده می کنیم. پس کد تابع Main که در بالا آورده شد، می تواند مثال خوبی از این نوع سطح دسترسی باشد.

2- قابل دسترسی در کل پکیج:

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

String mySite = "Gsm Developers;";

void mySiteMethod(){
           //code
       }

3- قابل استفاده در کلاس:

این نوع سطح دسترسی باعث می شود که آن متغیر و یا تابع، فقط در آن کلاس قابل دسترسی باشند. و بیرون از آن قابل استفاده نباشند.

برای این سطح دسترسی از private استفاده می شود. این سطح دسترسی محدود کننده ترین سطح دسترسی است. استفاده از دسترسی private راه کپسوله کردن و پنهان کردن اطلاعات کلاس از سایر کلاس ها است. برای مثال می توانید کد زیر را مشاهده کنید:

public class myJava{
       private String mySite = "Gsm Developers";

       public String getmySite(){
           return mySite;
       } 
    }

در کد بالا متغیر mySite یک متغیر از نوع String بوده که فقط در همین کلاس قابل استفاده است. حال اگر بخواهید از این متغیر در جای دیگری استفاده نمایید، می توانید یک تابع از نوع Public را تعریف نموده و متغیر mySite را برگرداند. در جاهای دیگری غیر از این کلاس از این تابع برای استفاده از متغیر mySite می توان بهره برد.

4- قابل استفاده در subClass:

برای این که متغیر یا متدی در کلاس پدر قابل دسترس باشد و همچنین در کلاس فرزند نیز قابل استفاده باشد ولی در جای دیگر این امر ممکن نباشد از این سطح دسترسی استفاده می کنیم. برای مشخص کردن این سطح دسترسی باید از کلمه کلیدی protected قبل از تعریف شناسه استفاده کرد. همچنین در هنگام استفاده از این Modifier شناسه در داخل پکیج نیز قابل دسترسی خواهد بود. کلاس ها و اینترفیس ها را نمی توان به صورت protected تعریف کرد.

در مورد وراثت و استفاده از Modifier از نوع Protected در کلاس ها در بخش وراثت ها بیشتر صحبت خواهیم کرد.

Modifierهای غیر دسترسی

Modifierهایی که در ادامه در مورد آن ها صحبت می کنیم، ربطی به سطح دسترسی ندارند. و هرکدام معنی جداگانه ای دارند.

1- Static : 

در بخش معرفی کلاس ها در مورد ساخت شی از کلاس، صحبت کردیم. برای این که بتوانیم به متدهای کلاس ها، مثلا کلاس String دسترسی داشته باشیم، باید ابتدا شی را از نوع کلاس String تعریف می نمودیم.

با استفاده از Static می توان، به متدها و متغیر های کلاس، بدون تعریف نمودن شی از آن کلاس، دسترسی پیدا کرد. همچنین بین همه اشیا مشترک نیز می باشد. به عبارتی، بدون آن که یک شی از کلاس بسازیم، اگر متد یا متغیری را از نوع Static معرفی کنیم، با استفاده از نام کلاس قابل دسترسی خواهد بود. و لازم به ساخت شی نخواهد بود.

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

package javaapplication1;

public class JavaApplication1 {

    public static class myJava{

        public static int myCount=0;

    }
    /**
     * @param args the command line arguments
     */
public static void main(String[] args) {

       myJava.myCount++;

       System.out.print(myJava.myCount);

    }

}

مشاهده می کنید که در تابع Main با استفاده از نام کلاس ، به متغیر دسترسی داشتیم و توانستیم مقدار آن را عوض کنیم. در هر جای برنامه نیز می توان به این متغیر دسترسی پیدا کرد.

همچنین اگر بعد از اجرای دستوری که در کد بالا، باعث شده مقدار متغیر myCount ، یک (1) شود، در جای دیگری از برنامه به این متغیر دسترسی پیدا کنیم، همین مقدار 1 را مشاهده می کنیم.

در صورتی که در ساخت اشیا از یک کلاس، متغیر هر تغییری که میکرد فقط مخصوص همان کلاس بود.

2- abstract :

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

توجه داشته باشید که نمیتوانید از کلاسی که از نوع abstract ساخته شده است، شی به صورت new بسازید.

همچنین اگر بخواهید متدی را در کلاسی به صورت abstract تعریف نمایید، باید خود آن کلاس به صورت abstract تعریف شود.

در مورد ارث بری در بخش های آینده صحبت خواهد شد.

public abstract class myJava{

        public abstract void myMethod();
        public void myMethod2(){
        // myMethod2 کدهای تابع 
        }       
    }

در کد بالا مشاهده می کنید که myMethod از نوع abstract تعریف شده است و اگر بخواهید بدنه آن را در این کلاس تعریف نمایید، کامپایلر خطا می دهد. پس باید در فرزند آن، بدنه ی تابع myMethod تعریف شود.

همچنین myMethod2 نیز که abstract نیست، برعکس myMethod اگر بدنه ی آن را تعریف نکنیم به مشکل می خوریم!

3- final :

در اینجا با یک Modifier مهم و پرکاربرد، مواجه هستیم. زمانی که کلاسی از نوع final تعریف می شود، دیگر نمیتواند فرزندی داشته باشد.

اولین نکته ای که به ذهن شما باید برسد اینست که اگر کلاسی از نوع final تعریف شود، نمی تواند از نوع abstract نیز تعریف شود و برعکس.

کاربرد این Modifier برای تعریف متود به این گونه است که، اگر متودی در کلاس پدر از نوع final تعریف شود، دیگر در کلاس فرزند ( در صورتی که کلاس پدر خود final نباشد) نمی توانید، متود را باز نویسی (Override) نمایید.

همچنین کاربرد final برای متغیر، به این گونه است که، زمانی که متغیری از نوع final تعریف می شود، فقط یک بار قابل مقداردهی است. و دیگر در جایی از برنامه نمی توان به آن مقدار داد.

کلاس:

public final class myJava{
} // نمی تواند فرزند داشته باشد..

متود:

public final void myMethod(){
        //
        } // در کلاس فرزند نمی تواند، باز نویسی شود

متغیر:

این کد خطاست زیرا متغیر m که از نوع final استفاده شده است، نمی تواند دو بار مقدار بگیرد.

final int m = 5;
m=6;

کد زیر صحیح است:

final int m;
m=6;

4- transient :

از کلمه کلیدی transient برای این منظور استفاده می شود که به ماشین مجازی جاوا (JVM) بفهمانیم که هنگامی که محتویات شی را سریالیز می کند، متغیری که به صورت transient تعریف شده است را نادیده بگیرد.

5- synchronized :

این کلمه کلیدی بدین منظور مورد استفاده قرار می گیرد که یک متد در یک زمان فقط توسط یک Thread قابل دسترسی باشد. این Modifier همراه با Modifierهای دسترسی نیز به کار می رود.

5- volatile :

اگر بخواهیم همزمان از چند Thread در برنامه استفاده کنیم، از کلمه کلیدی volatile استفاده می کنیم. منظور از استفاده از این Modifier این است که وقتی از این Modifier برای یک متغیر استفاده می کنیم به ماشین مجازی جاوا می گوییم که همه ی thread ها اگر متغیر مورد نظر را در حافظه کش خود تغییر بدهند باید آن تغییر بر روی متغیر در حافظه هم اعمال شود.

دلیل این کار این است که اگر چند thread به صورت همزمان از یک متغیر استفاده می کنند مقدار متغیر داده قدیمی نداشته باشد و همیشه همگام پیش برویم. این Modifier فقط بر روی فیلدهای کلاس قابل استفاده است. یک متغیر volatile می تواند null باشد.

public class MyThread implements Runnable{
    private volatile boolean active;

    public void run(){
        active = true;
        while (active){ 
            // Code
        }
    }

    public void stop(){
        active = false; 
    }
}

اگر کد run را توسط یک thread اجرا کنیم و اگر متد stop را توسط یک thread دیگر اجرا کنیم ممکن است که در خط while(active) از متغیر active یک کپی در حافظه کش مربوط به thread اجرا کننده موجود باشد.

بنابراین حتی اگر متد stop هم اجرا شود برنامه متوقف نمی شود. اما در این برنامه به دلیل این که متغیر active به صورت volatile معرفی شده است، اگر در متد stop مقدار این متغیر برابر False قرار بگیرد در همان زمان متد run هم متوقف خواهد شد

Arash

طراح سایت و برنامه نویس

یک دیدگاه

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا