برنامه نویسی جاوا – قسمت پنجم

جمعه, ۱۳ام آذر , ۱۳۸۸ | ۶ دیدگاه

متغیر ها

متغیر ها واحد پایه ذخیره سازی در برنامه های جاوا هستند .هر متغیری به وسیله ترکیبی از یک شناسه ؛ نوع و مقدار اولیه تعریف می شود به علاوه همه متغیر ها دارای محدودهScope و زمان حیات Life-Time هستند. محدوده هر متغیر مشخص می کند که آن متغیر در چه قسمتهایی قابل استفاده است.

شیوه تعریف کردن متغیر ها

شکل کلی تعریف کردن متغیر ها در جاوا اینگونه است:

Type identifier [=value][, identifier[=value]…];

Type یکی از انواع تجزیه ناپذیر جاوا ؛ نام یک کلاس یا رابط است identifier نام متغیر است  متغیر ها را می توان از طریق مشخص کردن یک علامت تساوی و یک مقدار مقداردهی نمود. حاصل عبارت مقداردهی باید مقداری از همان نوع مشخص شده برای متغیر باشد. کاما هم علامتی برای جدا کردن بیش از یک متغیر برای یک نوع است.

Int   a,b,c;   //declares three ints, a,b and c.

Int  d=3,e,f=5;     //declares   three more ints, initializing d and f.

Byte  z=22;

Double  pi =3.14159;

Char   x=’x’;

مقدار دهی اولیه پویا

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

//demonstrate dynamic initialization.

Class DynInit{

Public static void main(string args[])  {

Double  a=3.0 ,b=4.0;

//c is dynamically initialized

Double c= math.sqrt(a*a+b*b);

System.out.println(“ hypoyenuse is”+c);

}   }

C به طور پویا با طول وتر مقداردهی می شود.sqrt() یکی دیگر از متدهای توکار جاوا است که عضوی از کلاسmath است و جذر آرگومان خودش را محاسبه می کند. نکته کلیدی این نوع مقدار دهی این است که در عبارت مقداردهی می توان از هر عنصری که در زمان مقداردهی معتبر است استفاده نمود از جمله متدها ؛متغیر های دیگر یا حتی لیترال ها.

محدوده دستیابی و دوره حیات متغیر ها

تا به حال تمامی متغیر های مورد استفاده ؛در ابتدای متد main() تعریف شده اند اما جاوا امکان تعریف متغیر ها را در هر بلوکی فراهم کرده است. هر بلوک محدوده ای را تعیین می کند پس هر بار که بلوک جدیدی را آغاز می کنید محدوده جدیدی ایجاد می شود و هر محدوده تعیین می کند که کدام شی ء ها برای سایر بخش ها قابل رویت است. دوره حیات آن شی ء ها نیز مشخص می شود.

زبانها ی کامپیوتری دیگر دو دسته عمومی از محدوده ها را تعیین می کنند : عمومیglobal و محلی local اما این محدوده های قدیمی به خوبی با مدل شی ء گرای جاوا مطابقت ندارد . اگر چه امکان ایجاد متغیر هایی وجود دارد که در نهایت به داشتن یک محدوده عمومی منجر شود اما انجام این کار عموما یک استثنا به شمار می آید و نه یک قاعده کلی.

در زبان جاوا دو محدوده اصلی ؛ محدوده هایی هستند که توسط یک کلاس تعریف می شوند و نیز محدوده هایی که توسط یک متد تعریف می شوند.حتی این تمایز نیز قدری مصنوعی است اما چون محدوده کلاس چندید ویژگی و خصوصیت منحصر به فرد دارد که به محدوده تعریف شده توسط یک متد اعمال نمی شوند؛ این تمایز معقول به نظر می رسد. در حال حاضر تنها به بررسی محدوده هایی می پردازیم که توسط و یا درون یک متد تعریف می شوند.

محدوده ای که توسط هر متد تعریف می شود ؛ با آکولاد Brace باز آغاز می شود اما اگر آن متد پارامتر هایی داشته باشد؛ آنها نیز در محدوده آن متد قرار می گیرند. اگر چه در این درسنامه پارامتر ها را در آینده بررسی خواهیم کرد اما فعلا به خاطر این مبحث فرض می شود که آنها نیز همچون سایر متغیر ها کار می کنند.

به طور کلی؛ متغیر هایی که در یک محدوده تعریف می شوند؛ برای قسمت های خارج از آن محدوده قابل دسترسی نیستند از این رو وقتی متغیری را درون یک محدوده تعریف می کنیم؛ در واقع آن را محلی می سازیم و آن را در مقابل دستیابی و یا تغییرات غیر مجاز محافظت می کنیم. در حقیقت ؛ قوانین محدوده؛پایه و اساس لازم برای نهان سازیencapsulation را فراهم می سازیم.

محدوده ها ممکن است تودر توnested باشند. هر بار که  بلوکی ایجاد می کنیم در واقع محدوده جدید تودر تویی را ایجاد کرده ایم و با این عمل محدوده بیرونی؛ محدوده درونی را در بر می گیرد. این بدان معناست که شی ء های تعریف شده در محدوده بیرونی؛ برای دستورالعمل های محدوده درونی قابل رویت خواهند بود که البته عکس آن صادق نیست. برنامه زیر را در نظر بگیرید:

//demonstrate block scope.

Class Scope{

Public static void main(string args{})  {

Int  x;  // know to all code within main

X=10;

If(x==10) {//start new scope

Int y=20;  //know only to this block

//x and y both know here.

System.out.println(“ x and y :” +x+” “ +y);

X=y*2;}

//y=100;//error! Y not know here

//x is still know here

System.out.println(“x is” +x);

}

}

فکر می کنم برنامه خیلی گویا باشه در هر صورت اگه سوالی بود در خدمتم!

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

//this fragment is wrong!

Vount=100;  //oops!cannot use count before it is declared!

Int count,

همانطور که می بینید این عبارت اشتباه است چون متغیرcount پیش ار تعریف شدن قابل استفاده نیست.

به این نکته هم باید توجه کنید  که متغیر ها هنگام ورود به محدوده شان ایجاد می شوند و هنگام خروج از محدوده شان نیز از بین می روند. این بدان معناست که هیچ متغیری مقدارش را پس از خروج از محدوده اش نخواهد داشت بنابراین متغیر هایی که درون یک متد تعریف می شوند ؛ مقدارشان را در فواصل زمانی بین فراخوانی متد نخواهند داشت همچنین متغیری که در یک بلوک تعریف می شود مقدار را پس از خروج از بلوک از دست خواهد داد از این رو life-time هر متغیر به محدوده اش وابسته است.

اگر متغیری در حین تعریف مقداردهی شود ؛ در آن صورت هر بار به هنگام ورود به بلوک؛ از نو مقداردهی می شود:

//demonstrate lifetime of a variable.

Class LifeTime{

Public static void main(string args[])  {

Int x;

For (x=0;x<3;x++){

Int y=-1;  //y is initialized each time block is entered

System.out.printl(“y is: “ +y);   //this always -1

Y=100;

System.out.printl(“y is now:”  +y);

}

}

}

Out put:

Y is:-1

Y is now:100

Y is:-1

Y is now:100

Y is:-1

Y is now :100

همانگونه که می بینید هر بار به هنگام ورود به حلقه for متغیر y با ۱- مقداردهی می شود .با وجود آنکه مقدار۱۰۰ به آن اختصاص می یابد اما مقدار جدید را از دست می دهد.

و آخرین نکته: اگر چه بلوک ها می توانند تو در تو باشند اما نمی توان متغیری همنام با یکی از متغیر های محدوده بیرونی تعریف کرد:

//this program will not compile

Class ScopeErr{

Public static void main(string args[]) {

Int bar=1;

{       //creates a new scope

Int bar=2;    //compile time error—bar already defined!

}

}

}

تبدیل و Casting

اگر تجربه برنامه سازی داشته باشید( که دارید) حتما می دونید که تخصیص یک نوع مقدار به متغیری از نوع دیگر نسبتا متداول است. اگر آن دو نوع سازگار باشند در آن صورت جاوا عمل تبدیل را به صورت خودکار انجام خواهد داد اما همیشه تمام داده های مختلف سازگار نیستند و از این رو همه تبدیلات به طور ضمنی ممکن نیست. به عنوان نمونه هیچ تبدیلی برای double به byte تعریف نشده است.

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

تبدیل خودکار جاوا

وقتی یک نوع داده به متغیری از نوع دیگر تخصیص می یابد؛ چنانچه شرایط ذیل مهیا باشد عمل  تبدیل خودکار انجام می شود:

  • آن دو نوع سازگار باشند
  • نوع مقصد بزرگتر از نوع مبدا باشد

هرگاه این دو شرط برقرار باشد نوعی “تبدیل همراه با بزرگ سازی” widening conversion انجام می شود. مثلا نوع int همیشه برای نگهداری مقادیر byte به اندازه کافی بزرگ است بنابراین استفاده از عبارتcasting به صورت صریح ضرورت ندارد.

برای تبدیلات همراه با بزرگ سازی؛ انواع داده های عددی از جمله اعداد صحیح و اعشاری با ممیز شناور با یکدیگر سازگار هستند اما انواع داده های عددی با char یا  Boolean سازگار نیستند. همچنین char و Boolean با هم نیز سازگار نیستند.

انجام Casting برای انواع داده های ناسازگار

گفتیم که برای نوع هایی که با هم سازگار نیستند نمی توانیم از تبدیلات خودکار(با وجود مفید بودنشان) استفاده کنیم. مثلا اگر بخواهیم یک مقدارint را به مقدارbyte تخصیص بدهیم؛ این تبدیل به طور خودکار انجام نمی شود زیرا byte از int کوچکتر است . این نوع تبدیل گاهی “تبدیل همراه با کوچک سازی” نامیده می شود ؛چرا که مقدار int به طور صریح کوچکتر می شود تا در مقصد قابل ذخیره باشد. برای آنکه تبدیل دو نوع ناسازگار را انجام دهید باید ازcasting استفاده کنید ؛ یعنی نبدیل صریح انواع داده ها. به صورت زیر:

(target-type)  value

Target-type مشخص کننده نوع داده ای است که مقدار مورد نظر باید به آن تبدیل شود. مثال زیر را مرور می کنیم:

Int  a;

Byte  b;

//…

B=(byte)  a;

در عبارت بالاcasting از int به byte انجام می شود. چنانچه مقدار صحیح بزرگتر از محدوده byte باشد؛ مقدارش از طریق تقسیم بر محدوده byte و به دست آوردن باقیمانده تقسیم؛ کوچک می شود.

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

//demonstrate casts.

Class Conversion {

Public static void main(string args[] ) {

Byte  b;

Int i=257;

Double  d=323.142;

System.out.println(“\nConversion of int to byte.”);

B=(byte)  I;

System.out.println( “i and b”+i+ “ “ +b);

System.out.println(“\nConversion of double to int.”);

I=(int)d;

System.out.println(“d and I “+ “ “ +i);

System.out.println(“\nConversion of double to byte.”);

B=(byte)d;

System.out.println(“d and b”+d+” “+b);

}

}

Out put:

Conversion of int to byte.

۱ and b 257   ۱

Conversion of double to int.

D and I 323.142     ۳۲۳

Conversion of double to byte.

D and b 323.142    ۶۷

دوست دارد برام بنویسید که در این قطعه برنامه casting ها به چه نوعی انجام شده. کار سختی نیست هم برنامه رو دارید و هم خروجی اون رو.

ارتقاء خودکار انواع داده ها در عبارتها

علاوه بر عملیات تخصیص؛ تبدیل نوع داده ها در شرایط دیگر هم محتمل است: در عبارتها.

برای درک دلیل این امر مثال زیر را در نطر بگیرید. در برخی از عبارات دقت مورد نیاز برای یک مقدار میانجی گاهی اوقات از محدوده یکی از عملوند ها تجاوز می کند:

Byte a=40;

Byte  b=50;

Byte  c=100;

Int d=a*b/c;

نتیجه جمله میانجیa*b از محدوده عملوند ها تجاوز می کند. برای مدیریت این گونه مسائل؛ جاوا در حین ارزیابی عبارتها؛ عملوند های نوعbyte یا short را به طور خودکار به int ارتقا promote می دهد. یعنی جمله میانجیa*b ؛ با int انجام می شود نه byte. پس نتیجه جمله(۵۰*۴۰=۲۰۰۰) حتی با وجود اینکهa وb هر دو byte هستند؛ معتبر خواهد بود.

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

نکته: در مواقعی که از عواقب مسئله سر ریزoverflow آگاهی دارید باید از عمل Casting صریح استفاده کنید.

قوانین ارتقاء انواع داده ها

۱-      تمام مقادیرbyte و short به گونه ای که گفته شد به int ارتقاء می یابند

۲-      اگر یکی از عملوند ها از نوع long باشد کل عبارت به long ارتقاء می یابد.

۳-      اگر یکی از عملوندها از نوعfloat باشد در آن صورت کل عبارت به float ارتقاء می یابد.

۴-      و اگر یکی از عملوندها double باشد  نتیجه همdouble خواهد بود.

خوب این هم از درسنامه پنجم. درسنامه ششم اختصاص به آرایه ها داره که موضوع مهمی در تمام زبانهای برنامه نویسی است. اگه سوالی داشتید برام e-mail بفرستید:  schoneDame2294@yahoo.com

موفق و پیروز باشید

مینا هوشمند

Be Sociable, Share!


۶ دیدگاه


  1. محمد حسین ربیعی
    ۱۳ آذر ۱۳۸۸

    بسیار عالی

    لطفا در پایان آموزش فایل پی‌دی‌اف آموزش را قرار دهید




  2. محسن
    ۱۶ آذر ۱۳۸۸

    سلام
    یه دوتا نکته بود که لازم دونستم بگم!
    ۱- Double یه کلاسه ولی double داده گونه!
    ۲- Math نه math (کلاس با حروف بزرگ شروع می شن)!




  3. مينا
    ۹ دی ۱۳۸۸

    ممنون از تذکر به جای شما دوست عزیز



  4. […] برنامه نویسی جاو… متغیر ها […]




  5. shima
    ۱۹ بهمن ۱۳۹۰

    salam bazam khaste nabashim mishe narm afzari ke java estefade mikonaro vasam bezarid.mamnoon




  6. shima
    ۱۹ بهمن ۱۳۹۰

    albate jomleye ghabli khaste nashide dostan



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