PDA

نسخه کامل مشاهده نسخه کامل : همه چیز در مورد جاوا



Nesta
06-06-2005, 21:05
زمينه هاي پيدايش جاوا

تاريخچه زبانهاي برنامه نويسي بشرح زير است : زبان B منجر به ظهور زبان C و C
زمينه پيدايش C++ شد و در نهايت زبان جاوا متولد شد . درك زبان جاوا مستلزم :
درك زمينه هاي لازم براي ايجاد جاوا ، نيروهايي كه اين زبان را شكل داده اند و
مشخصاتي است كه اين زبان از اسلاف خود به ارث برده است . نظير ساير زبانهاي
برنامه نويسي موفق ، جاوا نيز عناصر بارث برده از اسلاف خود را با ايده هاي
ابتكاري كه ناشي از محيط منحصر بفرد اين زبان بوده درهم آميخته است . فصول بعدي
جنبه هاي عملي زبان جاوا شامل دستور زبان (syntax) و كتابخانه ها (libraries)
و كاربردهاي جاوا را توصيف مي كند . فعلا" چگونگي و علت ظهور جاوا و اهميت آن
را بررسي مي كنيم .
اگر چه جاوا تفكيك ناپذيري با محيط هاي همزمان اينترنت پيوستگي دارد ، اما
بخاطر بسپاريد كه جاوا قبل از هر چيز يك زبان برنامه نويسي است . ابداعات و
پيشرفت ها در زبانهاي برنامه نويسي كامپيوتر بدو دليل بروز مي كنند :
- تطابق با تغييرات محيط ها و كاربردها .
- ايجاد پالايش و پيشرفت در هنر برنامه نويسي .
همانطوريكه بعدا" مشاهده مي كنيد ، تولد جاوا از اين دو دليل بطور يكسان .

Nesta
06-06-2005, 21:06
انواع ساده The simple Types

جاوا هشت نوع ساده ( يا ابتدايي ) از داده را تعريف مي كند : short bbyte int
، long،، char،، float،، double،، boolean، اين انواع را مي توان در چهار
گروه بشرح زير دسته بندي نمود :
ؤ integers ( اعداد صحيح ) : اين گروه دربرگيرنده byte، short،، int،و longو
ميباشد كه مختص ارقام علامتدار مقدار كل (whole-valued signed numbers) ميباشد.
ؤ floating-point numbers ( اعداد اعشاري ) : اين گروه دربرگيرنده float و double
است كه معرف اعدادي است با دقت زياد .
ؤ characters ( كاراكترها ) : اين گروه فقط شامل char بوده كه نشانه هايي
نظير حروف و ارقام را در يك مجموعه خاص از كاراكترها معرفي مي كند .
ؤ Boolean ( بولي ) : اين گروه فقط شامل boolean است . كه نوع خاصي ازمعرفي
و بيان مقادير صحيح / ناصحيح مي باشد .
شما مي توانيد از اين انواع همانطوريكه هستند استفاده كرده ، يا آرايه ها و
انواع كلاسهاي خود را بسازيد .
انواع اتمي معرف مقادير تكي و نه اشيائ پيچيده هستند . اگر چه جاوا
همواره شي ئ گرا است ، اما انواع ساده اينطور نيستند . اين انواع ، مشابه انواع
ساده اي هستند كه در اكثر زبانهاي غير شي ئ گرا مشاهده مي شود . دليل اين امر
كارايي است . ساختن انواع ساده در اشيائ سبب افت بيش از حد كارايي و عملكرد
مي شود .
انواع ساده بگونه اي تعريف شده اند تا يك دامنه روشن و رفتاري رياضي داشته
باشند . و زبانهايي نظير Cو C++و امكان مي دهند تا اندازه يك عدد صحيح براساس
ملاحظات مربوط به محيط اجرايي تغيير يابد . اما جاوا متفاوت عمل مي كند . بدليل
نيازهاي موجود براي قابليت حمل جاوا ، كليه انواع داده در اين زبان داراي يك
دامنه كاملا" تعريف شده هستند . بعنوان مثال يك int هميشه 32 بيتي است ، صرفنظر
از اينكه زير بناي خاص محيطي آن چگونه باشد . اين حالت به برنامه هاي نوشته شده
اجازه مي دهد تا با اطمينان و بدون در نظر گرفتن معماري خاص يك ماشين اجرا
شوند. در حاليكه مشخص كردن دقيق اندازه يك عدد صحيح ممكن است در برخي محيط ها
سبب افت عملكرد شود ، اما براي رسيدن به خاصيت قابليت حمل پرداخت چنين تاواني

Nesta
06-06-2005, 21:07
( اعداد صحيح )

جاوا چهار نوع عدد صحيح تعريف مي كند : byte، short،، int،، long، . كليه
اين اعداد داراي علامات مثبت و منفي هستند . جاوا از اعداد صحيح غير علامت دار و
فقط مثبت پشتيباني نمي كند . بسياري از زبانهاي برنامه نويسي شامل Cو C++و هم
از اعداد صحيح علامت دار و هم از اعداد صحيح فاقد علامت پشتيباني مي كنند . اما
طراحان جاوا احساس مي كردند كه اعداد صحيح فاقد علامت غير ضروري است . بويژه
آنها احساس كردند كه مفهوم فاقد علامت (unsigned) بيشتر براي مشخص كردن رفتار
بيت بالاتر از حد مجاز (high-order bit) استفاده مي شود كه علامت يك int را
هنگاميكه بعنوان يك رقم عنوان مي شود ، مشخص مي كند . بعدا" خواهيد ديد كه
جاوا مفهوم بيت بالاتر از حد مجاز (high-order bit) را بگونه اي متفاوت مديريت
مي كند ، يعني با اضافه كردن يك عملگر ويژه حركت به راست فاقد علامت unsigned)
(right shift . بدين ترتيب نياز به يك نوع عدد صحيح فاقد علامت منتفي شده است .
پهناي (widit) يك نوع عدد صحيح را نبايد با ميزان حافظه اي كه مصرف مي كند
اشتباه گرفت ، بلكه نشانه رفتاري است كه براي متغيرها و عبارات آن نوع تعريف
مي شود . محيط حين اجراي جاوا از هر اندازه اي كه نياز داشته باشد ، استفاده
مي كند ، البته تا آن اندازه اي كه انواع براساس اعلام قبلي شما رفتار كنند . در
حقيقت ، حداقل يك پياده سازي byte وجود دارد كه ، short را بعنوان مقادير 32
بيتي ذخيره مي كند تا عملكرد را توسعه دهد. زيرا آنچه درحال حاضر مورد استفاده
قرار مي گيرد ، اندازه كلمه (word size) اكثر كامپيوترهاست .
پهنا و دامنه اين انواع اعداد صحيح همانطوريكه در جدول زير مشاهده مي كنيد
طيف وسيعي دارند :
دامنه پهنا نام
long 64- 9/ 223/ 372/ 036/ 845/ 775/ 808 to 9/ 223/ 372
/036/ 854/ 775/ 807
int 32- 2/ 147/ 483/ 648 to 2/ 147/ 483/ 647
short 16- 32/ 768 to 32/ 767
byte 8- 128 to 127

اكنون نگاه دقيقتري به هر يك از انواع عدد صحيح خواهيم داشت .
byte

كوچكترين نوع عدد صحيح byte است . اين يك نوع علامت دار 8 بيتي است كه دامنه
آن از 128- تا 127 مي باشد . متغيرهاي نوع byte بويژه هنگاميكه با يك جريان
داده از يك شبكه يا يك فايل كار ميكنيد ، سودمند خواهند بود . همچنين هنگاميكه
با داده دودويي ( باينري ) خام مشغول كار هستيد كه ممكن است بطور مستقيم با
ساير انواع توكار جاوا سازگاري نداشته باشند ، بسيار سودمند هستند .
متغيرهاي byte را با استفاده از واژه كليدي byte اعلام مي كنيم . بعنوان
مثال ، در زير دو متغير byte با اسامي bو cو را اعلام كرده ايم : + byte b/ c;

short

يك نوع 16 بيتي علامت داراست . دامنه آن از 768 32/- تا 767 32/ است . short
در اصل كم استفاده ترين نوع در جاوا مي باشد ، چون طوري تعريف شده كه بايت بالاي
آن اول مي آيد ( آن را big-endian format ميگويند ). اين نوع براي كامپيوترهاي 16
بيتي كه بسرعت از رده خارج شده اند ، كاربري دارد .
در زير مثالهايي از چگونگي اعلان متغيرهاي short را مشاهده مي كنيد : + short s;
+ short t;

نكته : Endiannes توصيف كننده چگونگي ذخيره شدن انواع داده چند بايتي short int
و longو در حافظه است . اگر 2 بايت براي معرفي يك نوع short استفاده
شود ، آن بايتي كه ابتدا قرار مي گيرد ( مهمترين يا كم اهميت ترين ? )
مي گويد كه يك ماشين big-endian است ، بدان معني كه مهمترين بايت اول
آمده و بعد از آن بايت كم اهميت تر قرار دارد . ماشينهايي نظير SPARC و power pc
از نوع big-endian و ماشينهاي سري lntelx86نوع little-endianع
هستند .
int

رايجترين نوع عدد صحيح int است . اين يك نوع 32 بيتي علامت دار است كه دامنه
آن از 2/147/483/648- تا 2/147/483/647 گسترده است . علاوه بر كاربردهاي ديگر
متغيرهاي از نوع int براي كنترل حلقه ها و نمايه سازي آرايه ها مورد استفاده قرار
مي گيرند . هر بار كه يك عبارت عدد صحيح شامل byte، short،و intو و ارقام لفظي
(literal) داشته باشيد، كل عبارت قبل از انجام محاسبات به int ارتقائ مي يابد.
نوع int روان ترين و كاراترين نوع است و اكثر اوقات هنگاميكه ميخواهيد رقمي
را براي شمارش يا نمايه سازي آرايه ها يا انجام محاسبات عدد صحيح بوجود آوريد
بايد از آن استفاده نماييد . شايد بنظر آيد كه استفاده از انواع shortو byteو
سبب صرفه جويي در فضا شود ، اما هيچ تضميني وجود ندارد كه جاوا اين انواع را
بطرق داخلي به int ارتقائ ندهد . همواره بياد داشته باشيد كه نوع ، مشخص كننده
رفتار است نه اندازه . ( تنها استثنائ در اين مورد، آرايه است كه در آنجا byte
بصورت تضميني براي هر عضو آرايه فقط يك بايت ، short دو بايت و int از چهار
بايت استفاده مي كند . )
long

يك نوع 64 بيتي علامت دار است و براي مواردي مفيد است كه يك نوع int طول
كافي براي دربرگرفتن مقدار مورد نظر نداشته باشد. دامنه long كاملا" وسيع است .
اين نوع ، براي كار با اعداد خيلي بزرگ مناسب است . بعنوان مثال ، در زير
برنامه اي را مشاهده مي كنيد كه مسافت طي شده توسط نور در تعداد مشخص روز را بر
حسب مايل محاسبه مي كند .

+ // Compute distance light travels using long variables.
+ class Light {
+ public static void main(String args[] ){
+ int lightspeed;
+ long days;
+ long seconds;
+ long distance;
+
+ // approximate speed of light in miles per second
+ lightspeed = 86000;
+
+ days = 1000; // specify number of days here
+
+ seconds = days * 24 * 60 * 60; // convert to seconds
+
+ distance = lightspeed * seconds; // compute distance
+
+ System.out.print("In " + days);
+ System.out.print(" days light will travel about ");
+ System.out.println(distance + " miles .");
+ }
+ }


خروجي اين برنامه بقرار زير خواهد بود : ln 1000 days light will travel about 4730400000000 miles.

Nesta
06-06-2005, 21:08
اصل و نسب جاوا

جاوا به زبان C++ ( نتيجه مستقيم زبان C ) وابسته است . بسياري از خصلتهاي
جاوا بطور مستقيم از اين دو زبان گرفته شده است . دستور زبان جاوا منتج از
دستور زبان C است . بسياري از جنبه هاي oop زبان جاوا از C++ بعاريت گرفته شده
است . در حقيقت بسياري از خصلتهاي زبان جاوا از اين دو زبان مشتق شده يا با
آنها مرتبط است . علاوه بر اين ، توليد جاوا بطور عميقي متاثر از روال پالايش و
تطبيقي است كه طي سه دهه گذشته براي زبانهاي برنامه نويسي موجود پيش آمده است .
بهمين دلايل بهتر است سير مراحل و نيروهايي كه منجر به تولد جاوا شده را بررسي
نماييم . هرنوع ابتكار و فكر جديد در طراحي زبانها براساس نياز به پشت سر نهادن
يك مشكل اصلي است كه زبانهاي قبلي از حل آن عاجز مانده اند . جاوا نيز بهمين
ترتيب متولد شد .

تولد زبان برنامه نويسي جديد : C
زبان C پس از تولد ، شوك بزرگي به دنياي كامپيوتر وارد كرد . اين زبان بطور
اساسي شيوه هاي تفكر و دستيابي به برنامه نويسي كامپيوتر را دگرگون ساخت . تولد C
ناشي از نياز به يك زبان ساخت يافته ، موثر و سطح بالا بعنوان جايگزيني براي
كدهاي اسمبلي و پياده سازي برنامه نويسي سيستم بود . هنگاميكه يك زبان برنامه
نويسي جديد متولد ميشود ، مقايسه ها شروع خواهد شد . مقايسه ها براساس معيارهاي
زير انجام مي گيرند :
ؤ راحتي كاربري در مقايسه با قدرتمندي زبان برنامه نويسي
ؤ ايمني در مقايسه با سطح كارآيي
ؤ استحكام در مقايسه با توسعه پذيري
قبل از ظهور زبان C برنامه نويسان با زبانهايي كار مي كردند كه قدرت
بهينه سازي يك مجموعه خاص از خصايص را داشتند . بعنوان مثال هنگاميكه از فرترن
براي نوشتن برنامه هاي موثر در كاربردهاي علمي استفاده مي كنيم ، برنامه هاي
حاصله براي كدهاي سيستم چندان مناسب نيست . زبان بيسيك با اينكه براحتي آموخته
مي شود ، اما قدرت زيادي نداشته و عدم ساخت يافتگي آن در برنامه هاي بزرگ مشكل
آفرين خواهد شد . از زبان اسمبلي براي توليد برنامه هاي كاملا" موثر استفاده
مي شود ، اما آموزش و كار با اين زبان بسيار مشكل است . بعلاوه اشكال زدايي
كدهاي اسمبلي بسيار طاقت فرساست .
مشكل اصلي ديگر اين بود كه زبانهاي اوليه برنامه نويسي نظير بيسيك ، كوبول
و فرترن براساس اصول ساخت يافته طراحي نشده بودند . اين زبانها از Goto بعنوان
ابزارهاي اوليه كنترل برنامه استفاده مي كردند . در نتيجه ، برنامه هاي نوشته
شده با اين زبانها توليد باصطلاح " كدهاي اسپاگتي "(spaghetti code() مي كردند
منظور مجموعه اي در هم تنيده از پرشها و شاخه هاي شرطي است كه درك يك برنامه
طولاني را ناممكن مي سازد . اگر چه زبانهايي نظير پاسكال ، ساخت يافته هستند
اما فاقد كارايي لازم بوده و جنبه هاي ضروري براي كاربرد آنها در طيف وسيعي از
برنامه ها وجود ندارد . ( بخصوص ويرايش پاسكال استاندارد فاقد ابزارهاي كافي
براي استفاده در سطح كدهاي سيستم بود . )
تا قبل از ابداع زبان C ، زبان ديگري قدرت نداشت تا خصلتهاي متضادي كه در
زبانهاي قبلي مشاهده ميشد ، را يكجا گردآوري كند . نياز به وجود يك چنين زباني
شديدا" احساس ميشد. در اوايل دهه 1970 ميلادي ، انقلاب رايانه اي در حال شكل گيري
بود و تقاضا براي انواع نرم افزارها فشار زيادي روي برنامه نويسان و تواناييهاي
ايشان اعمال ميكرد. درمراكز آموزشي تلاش مضاعفي براي ايجاد يك زبان برنامه نويسي
برتر انجام مي گرفت . اما شايد از همه مهمتر توليد و عرضه انبوه سخت افزار
كامپيوتري بود كه بعنوان يك نيروي ثانويه روي زبانهاي برنامه نويسي عمل ميكرد.
ديگر رايانه ها و اسرار دروني آنها پشت درهاي بسته نگهداري نمي شد . براي اولين
بار بود كه برنامه نويسان واقعا" دسترسي نامحدودي به اسرار ماشينهاي خود پيدا
نمودند . اين امر زمينه تجربيات آزادانه را بوجود آورد . همچنين برنامه نويسان
توانستند ابزارهاي مورد نيازشان را ايجاد نمايند . با ظهور زبان C ، زمينه
جهشهاي بزرگ در زبانهاي برنامه نويسي مهيا شد .
زبان C نتيجه توسعه تحقيقاتي درباره يك زبان قديمي تر بنام Bcpl بود . زبان C
اولين بار توسط Dennis Ritchie ابداع و روي ماشينهاي DEC PDP-11 داراي سيستم
عامل يونيكس اجرا شد . زبان Bcpl توسط Martin Richards توسعه يافته بود . Bcpl
منجر به تولد زبان B شد كه توسط Ken thompson ابداع شد و سرانجام به زبان C
منتهي شد . براي ساليان متمادي ، نسخه روايت استاندارد زبان C هماني بود كه
روي سيستم عامل unix عرضه و توسط Briian Kernighanو Dennis Ritchieو در كتاب "The C programming Language"
توصيف شده بود . بعدا" در سال 1989 ميلادي زبان C
مجددا" استاندارد شد وو استاندارد ANSI براي زبان C انتخاب شد .
بسياري معتقدند كه ايجاد زبان C راهگشاي دوران جديدي در زبانهاي برنامه نويسي
بوده است . اين زبان بطور موفقيت آميزي تناقضهاي موجود در زبان هاي برنامه نويسي
قبلي را مرتفع نمود . نتيجه فرآيند ايجاد زبان C ، يك زبان قدرتمند ، كارا و
ساخت يافته بود كه براحتي قابل آموزش و فراگيري بود . اين زبان يك ويژگي غير
محسوس اما مهم داشت : زبان C ، زبان برنامه نويسان بود . قبل از ابداع زبان C
زبانهاي برنامه نويسي يا جنبه هاي آموزشي داشته يا براي كارهاي اداري طراحي
ميشد . اما زبان C چيز ديگري بود . اين زبان توسط برنامه نويسان واقعي و درگير
با كارهاي جدي ، طراحي و پياده سازي شده و توسعه يافت . جنبه هاي مختلف اين
زبان توسط افرادي كه با خود زبان سر و كار داشته و برنامه نويسي مي كردند مورد
بررسي ، آزمايش و تفكر و تفكر مجدد قرار گرفته بود . حاصل اين فرآيند هم زباني
بود كه برنامه نويسان آن را دوست داشتند . در حقيقت زبان C بسرعت مورد توجه
برنامه نويسان قرار گرفت تا جايي كه برنامه نويسان نسبت به C تعصب خاصي پيدا
نمودند . اين زبان مقبوليت و محبوبيت زيادي در بين برنامه نويسان يافت . بطور
خلاصه زبان C توسط برنامه نويسان و براي برنامه نويسان طراحي شده است . بعدا"
مي بينيد كه جاوا نيز اين ويژگي را از اجداد خود بارث برده است .

نياز به C++
طي دهه 1970 و اوايل دهه 80 ميلادي زبان C نگين انگشتري برنامه نويسان بود و
هنوز هم در سطح وسيعي مورد استفده قرار مي گيرد . از آنجاييكه C يك زبان موفق
و سودمند بوده ، ممكن است بپرسيد چه نيازي به زبانهاي جديدتر وجود داشته است .
پاسخ شما يك كلمه يعني پيچيدگي (Complexity) است . طي تاريخ كوتاه برنامه نويسي
پيچيدگي فزاينده برنامه ها نياز براي شيوه هاي بهتر مديريت پيچيدگي را بوجود
آورده است . C++ پاسخي است به اين نياز مديريت پيچيدگي برنامه ها كه زمينه اصلي
پيدايش C++ بوده است .
شيوه هاي برنامه نويسي از زمان اختراع رايانه تاكنون بطور قابل توجهي تغيير
نموده اند . بعنوان مثال ، هنگاميكه رايانه ها اختراع شدند ، برنامه نويسي با
استفاده از دستور العملهاي باينري (Binary) ماشين انجام مي گرفت .
ماداميكه برنامه ها شامل حدود چند دستور العمل بود ، اين روش كارآيي داشت .
بموازات رشد برنامه ها زبان اسمبلي ابداع شد تا برنامه نويسان بتوانند برنامه هاي
بزرگتر و پيچيده تر را با استفاده از نشانه هايي كه معرف دستورالعملهاي ماشين
بودند ، بنويسند . اما پيشرفت و رشد برنامه ها همچنان ادامه يافت و زبانهاي سطح
بالايي معرفي شدند كه ابزارهاي مناسب براي مديريت پيچيدگي روزافزون برنامه ها را
در اختيار برنامه نويسان قرار مي دادند .
اولين زبان مطرح در اين زمينه فرترن بود . اگر چه فرترن اولين گام در اين
مسير بود، اما زباني است كه توسط آن برنامه هاي تميز و سهل الادراك نوشته ميشود.
در دهه 1960 ميلادي برنامه نويسي ساخت يافته مطرح شد . با استفاده از زبانهاي
ساخت يافته ، براي اولين بار امكان راحت نوشتن برنامه هاي بسيار پيچيده بوجود
آمد . اما حتي با وجود روشهاي برنامه نويسي ساخت يافته ، هنگاميكه يك پروژه به
اندازه معيني مي رسيد ، پيچيدگي آن از توان مديريت برنامه نويس خارج مي شد . در
اوائل دهه 1980 ميلادي بسياري از پروژه هاي مديريت برنامه نويسي از مرزهاي
برنامه نويسي ساخت يافته گذشتند . براي حل اين قبيل مشكلات ، يك روش نوين
برنامه نويسي ابداع شد . اين روش را برنامه نويسي شي ئ گرا يا باختصار oop
مي نامند . oop با جزئيات بيشتري بعدا" در همين كتاب بررسي خواهد شد ، اما
توصيف مختصر اين روش عبارت است از : oop يك نوع روش شناسي برنامه نويسي است كه
امكان سازماندهي برنامه هاي پيچيده از طريق بهره گيري از سه روش : وراثت ، كپسول
سازي و چند شكلي ، را ايجاد مي كند .
در تحليل نهايي ، اگر چه C بزرگترين و مهمترين زبان برنامه نويسي جهان است
اما محدوديتهايي در مديريت پيچيدگي برنامه ها دارد . هنگاميكه يك برنامه از
محدوده 25000 تا 100000 خط از كدها تجاوز نمايد، آنچنان پيچيده مي شود كه درك
آن بعنوان يك برنامه كلي ناممكن خواهد شد . C++ اين محدوديت را از بين برده و
به برنامه نويس كمك مي كند تا برنامه هايي از اين بزرگتر را نيز درك و مديريت
نمايد . C++
در سال 1979 ميلادي توسط Bjarne stoustrup هنگاميكه در آزمايشگاه بل در Marry Hill
ايالت New jersy مشغول كار بود ، ابداع شد . او در ابتدا اين زبان
جديد را (C with classes) ناميد . اما در سال 1983 ميلادي نام اين زبان جديد به C++
تغيير يافت . C++ تداوم زبان C بود كه جنبه هاي oop نيز به آن اضافه مي شد.
از آنجايي كه زبان C++ براساس زبان C شكل گرفته ، در بر گيرنده كليه جنبه ها
خسلتها (attributes) و مزاياي زبان C مي باشد . اين عوامل دلايل قاطعي براي
موفقيت حتمي C++ بعنوان يك زبان برنامه نويسي هستند . ابداع C++ در حقيقت تلاشي
براي ايجاد يك زبان كاملا" جديد برنامه نويسي نبود. در حقيقت پروژه C++ منجر به
افزايش تواناييهاي زبان موفق C شد .
چون C++ از ابتداي تولد تاكنون داراي روايتهاي گوناگوني شده است ، در حال
حاضر در تلاش استاندارد نمودن اين زبان هستند . ( اولين روايت پيشنهادي ANSI
براي استاندارد C++ در سال 1994 ميلادي مطرح شد . ) روال استاندارد سازي اين مچنان

Nesta
06-06-2005, 21:10
انواع اعداد اعشاري

اعداد اعشاري يا همان اعداد حقيقي براي ارزش گذاري عبارتهايي كه نيازمند
دقت بيشتري هستند ، استفاده مي شوند . بعنوان نمونه ، محاسباتي نظير ريشه دوم
و محاسبات مثلثاتي نظير سينوس و كسينوس منجربه جوابهايي مي شوند كه براي تعيين
دقت آن نياز به نوع عدد اعشاري مي باشد . جاوا يك مجموعه استاندارد (IEEE-754)
از انواع عدد اعشاري و عملگرها را پياده سازي مي كند. دو نوع عدد اعشاري تعريف
شده يعني floatو doubleو هستند كه بترتيب معرف دقت معمولي و مضاعف مي باشند .
پهنا و دامنه آنها را در زير نشان داده ايم :
دامنه پهنا بر حسب تعداد بيت نام
double 64 1.7e-308 to 1.7e+308
float 32 3.4e-038 to 3.4e+038

هر يك از انواع اعشاري را متعاقبا" مورد بررسي قرار مي دهيم .
float

اين نوع مشخص كننده يك مقدار با دقت معمولي بوده كه از 32 بايت حافظه
استفاده مي كند . دقت معمول روي بعضي پردازنده ها سريعتر بوده و نسبت به دقت
مضاعف نيمي از فضا را اشغال مي كند ، اما هنگاميكه مقادير خيلي بزرگ يا خيلي
كوچك باشند ، دقت خود را از دست ميدهد . متغيرهاي نوع float براي زماني مناسب
هستند كه از يك عضو كسري استفاده مي كنيد اما نيازي به دقت خيلي زياد نداريد .
بعنوان مثال ، نوع float براي معرفي دلار و سنت بسيار مناسب است . + float hightemp/ lowtemp;

double

دقت مضاعف كه با واژه كليدي double معين مي شود براي ذخيره كردن يك مقدار 64
بيت فضا را اشغال مي كند . دقت مضاعف روي برخي پردازنده هاي جديد كه براي
محاسبات رياضي با سرعت زياد بهينه شده اند ، واقعا" سريعتر از دقت معمولي عمل
مي كند . كليه توابع مثلثاتي نظير ()sin ، ()cos و ()sqrt مقادير مضاعف را
برمي گردانند . هنگام اجراي محاسبات مكرر كه نياز به حفظ دقت داريد و يا هنگام
كار با ارقام خيلي بزرگ double بهترين انتخاب است .
در زير برنامه اي را مشاهده مي كنيد كه از double استفاده نمود تا محيط يك
دايره را محاسبه كند :

+ // Compute the area of a circle.
+ class Area {
+ public static void main(String args[] ){
+ double pi/ r/ a;
+
+ r = 10.8; // radius of circle
+ pi = 3.1416; // pi/ approximately
+ a = pi * r * r; // compute area
+
+ System.out.println("Area of circle is " + a);
+ }
+ }



كاراكترها
در جاوا از نوع داده char براي ذخيره كردن كاراكترها استفاده مي شود . اما
برنامه نويسان Cو C++و آگاه باشند كه char در جاوا مشابه char در زبانهاي C و C++
نيست . در زبانهاي Cو C++و ، نوع char يك نوع عدد صحيح با پهناي 8 بيت
است . اما جاوا متفاوت عمل مي كند . جاوا از كدهاي جهاني (unicode) براي معرفي
كاراكترها استفاده مي كند . كدهاي جهاني يك مجموعه كاملا" جهاني از كاراكترها
هستند كه مي توانند همه كاراكترها را معرفي نمايند . اين مجموعه شامل دهها
مجموعه كوچك تر كاراكتري نظير Latin، Greek،، Arabic،، Cyrillic،، Hebrew، Katakana
، Hangul، و امثال آن است .
براي اين منظور ، 16 بيت مورد نياز است . بنابراين char در جاوا يك نوع 16
بيتي است . دامنه charاز 0ز تا 65/536 مي باشد . در نوع char مقدار منفي وجود
ندارد . مجموعه استاندارد كاراكترها موسوم به ASCII همچون گذشته داراي دامنه
از 0 تا 127 و مجموعه كاراكترهاي 8 بيتي توسعه يافته موسوم به lso-Latin-1
داراي دامنه از 0 تا 255 مي باشند .
چون در جاوا امكان نوشتن ريز برنامه ها براي كاربري جهاني وجود دارد ، بنظر
مي رسد كه بهتر است جاوا از كدهاي جهاني براي معرفي كاراكترها استفاده نمايد .
البته بكار بردن كدهاي جهاني درمورد زبانهايي نظير انگليسي ،آلماني ،اسپانيايي
يا فرانسوي كه كاراكترهاي آنها را مي توان براحتي داخل 8 بيت جاي داد ، تا حدي
سبب نزول كارآيي خواهد شد . اما اين بهايي است كه براي رسيدن به قابليت حمل
جهاني در برنامه ها بايد پرداخت .
نكته : اطلاعات بيشتر درباره كدهاي جهاني را در آدرسهاي وب زير پيدا خواهيد
نمود : [ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ] .unicode .org
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ] .stonehand .com/unicode .html


در زير برنامه اي را مشاهده مي كنيد كه متغيرهاي char را نشان مي دهد :


+ // Demonstrate char data type.
+ class CharDemo {
+ public static void main(String args[] ){
+ char ch1/ ch2;
+
+ ch1 = 88; // code for X
+ ch2 = 'Y';
+
+ System.out.print("ch1 and ch2 :");
+ System.out.println(ch1 + " " + ch2);
+ }
+ }


اين برنامه خروجي زير را نشان خواهد داد : ch1 and ch2 :xy

دقت كنيد كه مقدار 88به ch1 نسبت داده شده ، كه مقدار متناظر با حرف x در
كد ASCII ( و كد جهاني ) است . قبلا" هم گفتيم كه مجموعه كاراكتري ASCII َ127
مقدار اوليه در مجموعه كاراكتري كدهاي جهاني را اشغال كرده است . بهمين دليل
كليه فوت و فنهاي قديمي كه قبلا" با كاراكترها پياده كرده ايد ، در جاوا نيز به
خوبي جواب مي دهند .
اگر چه انواع char عدد صحيح محسوب نمي شوند ، اما در بسياري از شرايط
مي توانيد مشابه عدد صحيح با آنها رفتار كنيد . بدين ترتيب قادريد دو كاراكتر
را با هم جمع نموده و يا اينكه مقدار يك متغير كاركتري را كاهش دهيد . بعنوان
مثال ، برنامه زير را در نظر بگيريد :

+ // char variables behave like integers.
+ class CharDemo2 {
+ public static void main(String args[] ){
+ char ch1;
+
+ ch1 = 'X';
+ System.out.println("ch1 contains " + ch1);
+
+ ch1++; // increment ch1
+ System.out.println("ch1 is now " + ch1);
+ }
+ }


خروجي اين برنامه بشرح زير خواهد بود : ch1 contains x
ch1 is now y

در برنامه ابتدا مقدار xبه ch1 داده ميشود . سپس ch1 افزايش مي يابد . اين
روال باعث مي شود تا ch1 حرف y را اختيار كند، كه كاراكتر بعدي در ترتيب ASCII
( و كدهاي جهاني ) مي باشد .
Boolean

جاوا يك نوع ساده موسوم به boolean براي مقادير منطقي دارد . اين نوع فقط
يكي از مقادير ممكن trueيا falseا را اختيار مي كند . اين نوعي است كه توسط
كليه عملگرهاي رابطه اي نظير b شرطي كه دستورهاي كنترلي نظير ifو forو را مديريت مي كنند ، استفاده مي شود .
در زير برنامه اي مشاهده مي كنيد كه نوع boolean را نشان مي دهد :

+ // Demonstrate boolean values.
+ class BoolTest {
+ public static void main(String args[] ){
+ boolean b;
+
+ b = false;
+ System.out.println("b is " + b);
+ b = true;
+ System.out.println("b is " + b);
+
+ // a boolean value can control the if statement
+ if(b )System.out.println("This is executed.");
+
+ b = false;
+ if(b )System.out.println("This is not executed.");
+
+ // outcome of a relational operator is a boolean value
+ System.out.println("10 > 9 is " +( 10 > 9));
+ }
+ }


خروجي برنامه فوق بقرار زير خواهد بود :

b is false
b is true
This is executed.
10>9 is true


درباره اين برنامه سه نكته جالب توجه وجود دارد . اول اينكه وقتي كه مقدار boolean
توسط ()println خارج مي شود ، مي بينيد كه "true"يا "false"ا بنمايش
درمي آيد . دوم اينكه يك متغير boolean بتنهايي براي كنترل دستور if كفايت
مي كند . ديگر نيازي به نوشتن يك دستور if بقرار زير نخواهد بود : + if(b == true... )

يك مقدار <سوم اينكه ، پي آمد يك عملگر رابطه اي نظير boolean است . بهمين
دليل است كه عبارت 9>َ10 مقدار true را نمايش مي دهد . علاوه بر اين ، مجموعه ي از پرانتزهايي كه عبارت 9>َ10 را محصور كرده اند ، ضروري است زيرا عملگر +

Nesta
06-06-2005, 21:10
نگاهي دقيقتر به الفاظ

اكنون كه انواع توكار را بطور رسمي توضيح داده ايم ، نگاه دقيقتري به اين
الفاظ خواهيم داشت .

الفاظ عدد صحيح integer literals
احتمالا" اعداد صحيح رايجترين نوع استفاده شده در برنامه هاي نوع بندي شده
هستند. هر مقدار رقمي كلي يك لفظ عدد صحيح است . اعداد 1، 2،، 3، و 42 مثالهاي
روشني هستند . اين اعداد همگي مقادير دهدهي مي باشند ، بدين معني كه اين اعداد
در يك مبناي ده رقمي تعريف شده اند . دو مبناي ديگر نيز در الفاظ عدد صحيح قابل
استفاده هستند : مبناي هشت (octal) و مبناي 16(hexadecimal(). مقادير در مبناي
هشت در جاوا با يك رقم 0 پيش آيند مشخص ميشوند. ارقام دهدهي معمولي نمي توانند
رقم 0 پيش آيند داشته باشند . بنابراين مقدار بظاهر معتبر 09 خطايي را در
كامپايلر توليد مي كند، زيرا رقم 9 خارج از دامنه 0تا 7ا مبناي هشت قرار دارد.
يكي ديگر از مبناهاي رايج براي ارقام مورد استفاده برنامه نويسان ، مبناي 16
مي باشد كه با مدول اندازه هاي كلمه 8 تايي نظير 8 ، 16 ، 32 و 64 بيتي كاملا"
سازگاري دارد . يك ثابت درمبناي 16 را توسط OXيا oxا مشخص مي كنيد . دامنه يك
رقم در مبناي 16 از رقم 0 تا 15 و حروف Aتا Fا ( يا aتا fا ) بعنوان جايگزين
ارقام 10 تا 15 مي باشد .
الفاظ عدد صحيح يك مقدار int توليد مي كنند كه در جاوا يك مقدار عدد صحيح 32
بيتي است . از آنجاييكه جاوا شديدا" نوع بندي شده است ، ممكن است تعجب كنيد
كه چگونه مي توان يك لفظ عدد صحيح را به يكي ديگر از انواع عدد صحيح جاوا نظير byte
يا longا نسبت داد ، بدون اينكه خطاي عدم سازگاري انواع بوجود آيد .
خوشبختانه چنين حالتهايي بسادگي اداره مي شوند . هنگاميكه يك لفظ عدد صحيح به
يك متغير byteيا shortا منتسب مي شود، اگر مقدار لفظ داخل محدوده نوع هدف قرار
داشته باشد ، خطايي توليد نخواهد شد . همچنين همواره مي توان يك لفظ عدد صحيح
را به يك متغير long منتسب نمود . اما براي مشخص نمودن يك لفظ long بايد بطور
صريح به كامپايلر بگوييد كه مقدار لفظ از نوع long است . اينكار را با الحاق
يك حرف L بزرگ يا كوچك به لفظ انجام مي دهيم . بعنوان مثال ، ox7ffffffffffffffL 9223372036854775807L
بزرگترين Long مي باشد .

الفاظ عدد اعشاري Floating-point literals
ارقام اعشاري معرف مقادير دهدهي با اجزائ كسري مي باشند . آنها را مي توان
به شكل استاندارد يا به شكل علامتگذاري علمي بيان نمود . نشانه گذاري استاندارد
شامل يك جزئ عدد صحيح است كه بعد از آن يك نقطه و بعد از آن جزئ كسري عدد قرار
مي گيرد . بعنوان مثال 2.0 يا 3.14159 يا 0.6667 معرف نشانه گذاري استاندارد
معتبر در ارقام اعشاري هستند . نشانه گذاري علمي از يك نشانه گذاري استاندارد
نقطه مخصوص اعشاري بعلاوه يك پيوند كه مشخص كننده تواني از عدد 10 است كه
بايد در عدد ضرب شود استفاده مي كند . توان ( نما ) را توسط علامت Eيا eا كه
يك رقم دهدهي بدنبال آن مي آيد و ممكن است مثبت يا منفي باشد ، نشان مي دهيم .
مثل 6.022E23 يا 05-314159E و 2e+100 .
الفاظ عدد اعشاري در جاوا بصورت پيش فرض داراي دقت مضاعف (double) هستند .
براي مشخص نمودن يك لفظ float بايد يك حرف Fيا fا را به ثابت الحاق نماييد .
همچنين ميتوانيد بطور صريح يك لفظ double را با الحاق يك حرف Dيا dا نيز انجام
دهيد . انجام اينكار البته اضافي است . نوع double پيش فرض 64 بيت حافظه را
مصرف مي كند در حاليكه نوع كم دقت تر float مستلزم 32 بيت حافظه است .

الفاظ Boolean
الفاظ boolean بسيار ساده هستند. يك مقدار boolean فقط دو مقدار منطقي شامل true
و falseو مي تواند داشته باشد . مقادير trueو falseو هرگز به رقم تبديل
نمي شوند . در جاوا لفظ true مساوي يك نبوده ، همچنانكه لفظ false معادل صفر
نيست . در جاوا ، آنها را فقط مي توان به متغيرهاي اعلان شده بعنوان boolean
منتسب نمود و يا در عباراتي با عملگرهاي boolean استفاده نمود .

الفاظ كاراكترها Character literals
كاراكترهاي جاوا در مجموعه كاراكتر كدهاي جهاني نمايه سازي شده اند . آنها
مقادير 16 بيتي هستند كه قابل تبديل به اعداد صحيح بوده و با عملگرهاي عدد
صحيح نظير عملگرهاي اضافه و كسر نمودن اداره مي شوند . يك كاراكتر لفظي همواره
داخل يك علامت ' ' معرفي مي شود . كليه كاراكترهاي ASCII قابل رويت مي توانند
بطور مستقيم به داخل اين علامت وارد شوند ، مثل 'a'يا 'z'ايا '@'ا . براي
كاراكترهايي كه امكان ورود مستقيم را ندارند ، چندين پيش آيند وجود دارند كه
امكان ورود كاراكتر دلخواه را فراهم مينمايند، نظير '\' براي ورود خود كاراكتر
و '\n' براي كاراكتر خط جديد . همچنين مكانيسمي براي ورودي مستقيم مقدار يك
كاراكتر در مبناي هشت يا شانزده وجود دارد . براي نشانه گذاري مبناي هشت از
علامت \ كه توسط يك عدد سه رقمي دنبال ميشود، استفاده كنيد. بعنوان مثال '\141'
همان حرف 'a' است . براي مبناي شانزده از علامت (\u) استفاده كنيد و بعد از آن
دقيقا" چهار رقم مبناي شانزده . بعنوان مثال '\uoo61' كه معادل حرف 'a' در
استاندارد lso-latin-1 است چون بايت بالايي آن صفر است . '\ua432' يك كاراكتر Katakana
ژاپني است . جدول زير پيش آيندهاي كاراكترها را نشان مي دهد .

|
توصيف آن پيش آيند | |
كاراكتر مبناي هشت (ddd) \ddd | |
كاراكتر كد جهاني مبناي شانزده (xxxx) \uxxxx | |
علامت تكي نقل قول \' | |
علامت جفتي نقل قول \" | | \\ Backslash |
|
كاراكتر برگشت به سر خط \r | |
خط جديد \n | |
تغذيه فرم \f | | \t Tab |
| \b Backspace |



الفاظ String
الفاظ رشته اي در جاوا نظير ساير زبانهاي برنامه نويسي مشخص مي شوند قرار
دادن يك دنباله از كاراكترها بين يك جفت از علامات نقل قول ، در زير نمونه هايي
از الفاظ رشته اي را مشاهده مي كنيد .

"Hello world"
"tow\nlines"
"\"This is in quotes\"


پيش آيندها و نشانه گذاريهاي مبناي هشت / شانزده كه براي الفاظ كاراكترها
توصيف شد ، بهمان روش در داخل الفاظ رشته اي كار مي كنند . يك نكته مهم درباره
رشته هاي جاوا اين است كه آنها بايد روي يك خط شروع شده و پايان يابد . برخلاف
زبانهاي ديگر در جاوا ادامه خط در خطهاي ديگر مجاز نيست .
نكته : حتما" مي دانيد كه در اكثر زبانهاي ديگر شامل Cو C++و ، رشته ها بعنوان
آرايه هاي كاراكتري پياده سازي مي شوند . اما در جاوا اين حالت وجود
ندارد . رشته ها از نوع اشيائ هستند . بعدا" مي بينيد از آنجاييكه جاوا ياده سازي مي كند ، دربرگيرنده تواناييهاي

Nesta
06-06-2005, 21:12
متغيرها

در يك برنامه جاوا ، متغير ، اساسي ترين واحد ذخيره سازي است . يك متغير به
وسيله تركيبي از يك شناسه ، يك نوع و يك مقدار ده اوليه اختياري تعريف خواهد
شد . علاوه بر اين ، كليه متغيرها داراي يك قلمرو هستند كه رويت پذيري آنها را
تعريف مي كند و يك زمان حيات نيز دارند. متعاقبا" اين اجزائ را مورد بررسي
قرار مي دهيم .

اعلان يك متغير Declaring a variable
در جاوا كليه متغيرها قبل از استفاده بايد اعلان شوند . شكل اصلي اعلان متغير
بقرار زير مي باشد : type identifier [=value] [/identifier[=value]...];

مقدار شناسه مقدار شناسه نوع
نوع (type) يكي از انواع اتمي جاوا يا نام يك كلاس يا رابط است . ( انواع
كلاس و رابط بعدا" بررسي خواهد شد . ) شناسه نام متغير است . مي توانيد با
گذاشتن يك علامت تساوي و يك مقدار ، متغير را مقدار دهي اوليه نماييد . در ذهن
بسپاريد كه عبارت مقدار دهي اوليه بايد منتج به يك مقدار از همان نوعي ( يا
سازگار با آن نوع ) كه براي متغير مشخص شده ، گردد . براي اعلان بيش از يك نوع
مشخص شده ، از فهرست كاماهاي (') جدا كننده استفاده نماييد .
در زير مثالهايي از اعلان متغير از انواع گوناگون را مشاهده مي كنيد . دقت
كنيد كه برخي از آنها شامل يك مقدار دهي اوليه هستند .

+ 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; // initializes z.
+ double pi = 3.14159; // declares an approximation of pi.
+ char x = 'x'; // the variable x has the value 'x'.


شناسه هايي كه انتخاب مي كنيد هيچ عامل ذاتي در نام خود ندارند كه نوع آنها
را مشخص نمايد . بسياري از خوانندگان بياد مي آورند زماني را كه FORTRAN كليه
شناسه هاي از Iتا Nا را پيش تعريف نمود تا از نوع INTEGER باشند ، در حاليكه
ساير شناسه ها از نوع REAL بودند . جاوا به هر يك از شناسه هاي متناسب شكل گرفته
امكان اختيار هر نوع اعلان شده را داده است .

مقدار دهي اوليه پويا Dynamic intialization
اگر چه مثالهاي قبلي از ثابت ها بعنوان مقدار ده اوليه استفاده كرده اند
اما جاوا امكان مقداردهي اوليه بصورت پويا را نيز فراهم آورده است . اين موضوع
با استفاده از هر عبارتي كه در زمان اعلان متغير باشد ، انجام مي گيرد .
بعنوان مثال ، در زير برنامه كوتاهي را مشاهده مي كنيد كه طول ضلع يك مثلث
قائم الزاويه را با داشتن طول دو ضلع مقابل محاسبه مي كند :

+ // 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("Hypotenuse is " + c);
+ }
+ }


در اينجا سه متغير محلي a، b،، c، اعلان شده اند . دو تاي اولي توسط
ثابت ها مقدار دهي اوليه شده اند . اما متغير C بصورت پويا و بر حسب طول اضلاع
مثلث قائم الزاويه ( بنابر قانون فيثاغورث ) مقدار دهي اوليه مي شود . اين
برنامه از يكي از روشهاي توكار جاوا يعني ()sqrt كه عضوي از كلاس Math بوده و
ريشه دوم آرگومانهاي خود را محاسبه ميكند استفاده كرده است . نكته كليدي اينجا
است كه عبارت مقدار دهي اوليه ممكن است از هر يك از اجزائ معتبر در زمان مقدار
دهي اوليه ، شامل فراخواني روشها ، ساير متغيرها يا الفاظ استفاده نمايد .

قلمرو زمان حيات متغيرها
تابحال كليه متغيرهاي استفاده شده ، در زمان شروع روش ()main اعلان مي شدند.
اما جاوا همچنين به متغيرها امكان مي دهد تا درون يك بلوك نيز اعلام شوند .
همانطوريكه قبلا" توضيح داديم ، يك بلوك با يك ابرو باز و يك ابرو بسته محصور
مي شود : يك بلوك تعريف كننده يك قلمرو است . بدين ترتيب هر بار كه يك بلوك
جديد را شروع ميكنيد ، يك قلمرو جديد نيز بوجود مي آوريد . همانطوريكه احتمالا"
از تجربيات برنامه نويسي قبلي بياد داريد ، يك قلمرو (scope) تعيين كننده آن
است كه چه اشيائي براي ساير بخشهاي برنامه قابل رويت هستند . اين قلمرو همچنين
زمان حيات (lifetime) آن اشيائ را تعيين مي كند .
اكثر زبانهاي كامپيوتري دو طبقه بندي از قلمروها را تعريف مي كنند : سراسري
(global) و محلي (local) . اما اين قلمروهاي سنتي بخوبي با مدل موكد شي ئ گرايي
جاوا مطابقت ندارند . اگر چه در جاوا هم مي توان مقاديري را بعنوان قلمرو
سراسري ايجاد نمود ، اما اين فقط يك نوع استثنائ است و عموميت ندارد . در جاوا
قلمرو اصلي همانهايي هستند كه توسط يك كلاس يا يك روش تعريف مي شوند . حتي همين
تمايز نيز تا حدي ساختگي و مصنوعي است . اما از آنجاييكه قلمرو كلاس داراي
مشخصات و خصلتهاي منحصر بفردي است كه قابل استفاده در قلمرو تعريف شده توسط
روش نيست ، اين تمايز تا حدي محسوس خواهد بود . بخاطر تفاوتهاي موجود ، بحث
قلمرو كلاس ( و متغيرهاي اعلان شده داخل آن ) اين مبحث بتعوق افتاده است . در حال
حاضر فقط قلمروهاي تعريف شده توسط يك روش يا داخل يك روش را بررسي مي كنيم .
قلمرو تعريف شده توسط يك روش با يك ابروي باز شروع مي شود. اما اگر آن روش
داراي پارامترهايي باشد ، آنها نيز داخل قلمرو روش گنجانده خواهند شد . بعدا"
نگاه دقيقتري به پارامترها خواهيم داشت و فعلا" كافي است بدانيم كه پارامترها
مشابه هر متغير ديگري در يك روش كار مي كنند .
بعنوان يك قانون عمومي ، متغيرهاي اعلان شده داخل يك قلمرو براي كدهايي كه
خارج از قلمرو تعريف مي شوند ، قابل رويت نخواهند بود ( قابل دسترسي نيستند ).
بدين ترتيب ، هنگاميكه يك متغير را درون يك قلمرو اعلان مي كنيد ، در حقيقت آن
متغير را محلي دانسته و آن را در مقابل دستيابيها و تغييرات غير مجاز محافظت
مي كنيد . در حقيقت ، قوانين قلمرو اساس كپسول سازي را فراهم مي كنند .
قلمروها را مي توان بصورت تودرتو (nesting) محفوظ داشت . بعنوان مثال ، هر
زمان يك بلوك كد ايجاد كنيد ، يك قلمرو جديد تودرتو ايجاد نموده ايد . هنگاميكه
اين واقعه روي مي دهد ، قلمرو بيروني ، قلمرو دروني را دربرمي گيرد . اين بدان
معني است كه اشيائ اعلان شده در قلمرو بيروني براي كدهاي داخل قلمرو دروني قابل
رويت هستند اما عكس اين قضيه صادق نيست . اشيائاعلان شده داخل قلمرو دروني براي
بيرون قلمرو قابل رويت نخواهند بود .
براي درك تاثير قلمروهاي تودرتو ، برناه ريز را در نظر بگيريد :

+ // Demonstrate block scope.
+ class Scope {
+ public static void main(String args[] ){
+ int x; // known to all code within main
+
+ x = 10;
+ if(x == 10 ){ // start new scope
+ int y = 20; // known only to this bock
+
+ // x and y both known here.
+ System.out.println("x and y :" + x + " " + y);
+ x = y * 2;
+ }
+ // y = 100 :// Error! y not known here
+
+ // x is still known here.
+ System.out.println("x is " + x);
+ }
+ }


همانطوريكه توضيحات نشان مي دهند ، متغير x در ابتداي قلمروي ()main اعلان
شده و براي كليه كدهاي متعاقب داخل ()main قابل دسترسي مي باشد . داخل بلوك if
متغير y اعلان شده است . از آنجاييكه يك بلوك معرف يك قلمرو است ، y فقط براي
ساير كدهاي داخل بلوك خود قابل رويت است . اين دليل آن است كه خارج بلوك
مربوطه ، خط y=100 در خارج توضيح داده شده است . اگر نشانه توضيح راهنمايي را
تغيير مكان دهيد ، يك خطاي زمان كامپايل (compile-time error) اتفاق مي افتد
چون y براي بيرون از بلوك خود قابل رويت نيست . داخل بلوك if متغير x قابل
استفاده است زيرا كدهاي داخل يك بلوك ( منظور يك قلمرو تودرتو شده است ) به
متغيرهاي اعلان شده در يك قلمرو دربرگيرنده دسترسي دارند .
داخل يك بلوك ، در هر لحظه اي مي توان متغيرها را اعلان نمود ، اما فقط زماني
معتبر مي شوند كه اعلان شده باشند . بدين ترتيب اگر يك متغير را در ابتداي يك
روش اعلان مي كنيد، براي كليه كدهاي داخل آن روش قابل دسترس خواهد بود. بالعكس
اگر يك متغير را در انتهاي يك بلوك اعلان كنيد ، هيچ فايده اي ندارد چون هيچيك
از كدها به آن دسترسي ندارند . بعنوان مثال اين قطعه از برنامه غير معتبر است
چون نمي توان از count قبل از اعلان آن استفاده نمود :

+ // This fragment is wrong!
+ count = 100; // oops! cannot use count before it is declared!
+ int count;


يك نكته مهم ديگر در اينجا وجود دارد كه بايد بخاطر بسپاريد: متغيرها زماني
ايجاد مي شوند كه قلمرو آن ها وارد شده باشد ، و زماني خراب مي شوند كه قلمرو
آنها ترك شده باشد . يعني يك متغير هربار كه خارج از قلمروش برود ، ديگر مقدار
خود را نگهداري نخواهد كرد . بنابراين ، متغيرهاي اعلان شده داخل يك روش مقادير
خود را بين فراخواني هاي آن روش نگهداري نمي كنند . همچنين يك متغير اعلان شده
داخل يك بلوك ، وقتي كه بلوك ترك شده باشد ، مقدار خود را از دست خواهد داد .
بنابراين ، زمان حيات (lifetime) يك متغير محدود به قلمرو آن مي باشد .
اگر اعلان يك متغير شامل مقدار دهي اوليه آن باشد ، آنگاه هر زمان كه به
بلوك مربوطه وارد شويم ، آن متغير مجددا" مقدار دهي اوليه خواهد شد . بعنوان
مثال برنامه زير را در نظر بگيريد :

+ // 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.println("y is :" + y); // this always prints- 1
+ y = 100;
+ System.out.println("y is now :" + y);
+ }
+ }
+ }


خروجي توليد شده توسط اين برنامه بقرار زير است :

y is- :1
y is now:100
y is- :1
y is now:100
y is- :1
y is now:100


همانطوريكه مشاهده مي كنيد ، هر بار كه به حلقه for داخلي وارد مي شويم ، y
همواره بطور مكرر مقدار اوليه 1- را اختيار مي كند . اگر چه بلافاصله به اين
متغير مقدار 100 نسبت داده مي شود، اما هر بار نيز مقدار خود را از دست ميدهد.
و بالاخره آخرين نكته : اگر چه ميتوان بلوكها را تودرتو نمود، اما نميتوانيد
متغيري را اعلان كنيد كه اسم آن مشابه اسم متغيري در قلمرو بيروني باشد. از اين
نظر جاوا با زبانهاي Cو C++و متفاوت است . در زير مثالي را مشاهده مي كنيد كه
در آن تلاش شده تا دو متغير جدا از هم با اسم اعلان شوند . در جاوا اينكار مجاز
نيست . در Cو C++و اين امر مجاز بوده و دو bar كاملا" جدا خواهند ماند .

+ // 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!
+ }
+ }
+ }



تبديل خودكار و تبديل غير خودكار انواع
اگر تجربه قبلي برنامه نويسي داشته ايد ، پس مي دانيد كه كاملا" طبيعي است كه
مقداري از يك نوع را به متغيري از نوع ديگر نسبت دهيم . اگر اين دو نوع سازگار
باشند ، آنگاه جاوا بطور خودكار اين تبديل (conversion) را انجام مي دهد .
بعنوان مثال ، همواره امكان دارد كه مقدار int را به يك متغير long نسبت داد .
اما همه انواع با يكديگر سازگاري ندارند ، بنابراين هر گونه تبديل انواع مجاز
نخواهد بود . بعنوان نمونه ، هيچ تبديلي از doubleبه byte تعريف نشده است .
خوشبختانه ، امكان انجام تبديلات بين انواع غير سازگار هم وجود دارد . براي
انجام اينكار ، بايد از تبديل cast استفاده كنيد كه امكان يك تبديل صريح بين
انواع غير سازگار را بوجود مي آورد . اجازه دهيد تا نگاه دقيقتري به تبديل
خودكار انواع و تبديل cast داشته باشيم .

تبديل خودكار در جاوا Java's Automatic conyersions
هنگاميكه يك نوع داده به يك متغير از نوع ديگر نسبت داده مي شود ، اگر دو
شرط زير فراهم باشد ، يك تبديل خودكار نوع انجام خواهد شد :
ؤ دو نوع با يكديگر سازگار باشند .
ؤ نوع مقصد بزرگتر از نوع منبع باشد .
هنگاميكه اين دو شرط برقرار باشد ، يك تبديل پهن كننده (widening) اتفاق
مي افتد . براي مثال نوع int همواره باندازه كافي بزرگ است تا كليه مقادير
معتبر byte را دربرگيرد، بنابراين نيازي به دستور صريح تبديل cast وجود ندارد.
در تبديلات پهن كننده ، انواع رقمي شامل انواع عدد صحيح و عدد اعشاري با هر
يك از انواع سازگاري دارند . اما انواع رقمي با انواع charو booleanو سازگار
نيستند . همچنين انواع charو booleanو با يكديگر سازگار نيستند .
همانطوريكه قبلا" ذكر شد ، جاوا هنگام ذخيره سازي يك ثابت عدد صحيح لفظي
(Literal integer constant) به متغيرهاي از انواع byte، short،و longو ، يك
تبديل خودكار نوع را انجام مي دهد .

تبديل غير خودكار انواع ناسازگار
اگر چه تبديلات خودكار انواع بسيار سودمند هستند ، اما جوابگوي همه نيازها
نيستند . بعنوان مثال ، ممكن است بخواهيد يك مقدار int را به يك متغير byte
نسبت دهيد. اين تبديل بطور خودكار انجام نمي گيرد، زيرا يك byteاز intز كوچكتر
است .اين نوع خاص از تبديلات را گاهي تبديل باريك كننده (narrowing conversions)
مي نامند ، زيرا بطور صريح مقدار را آنقدر باريك تر و كم عرض تر مي كنيد تا با
نوع هدف سازگاري يابد .
براي ايجاد يك تبديل بين دو نوع ناسازگار ، بايد از cast استفاده نماييد . cast
يك تبديل نوع كاملا" صريح است . شكل عمومي آن بقرار زير مي باشد : ( target - type )value

نوع نوع مقصد يا هدف
در اينجا نوع هدف ، همان نوعي است كه مايليم مقدار مشخص شده را به آن تبديل
كنيم . بعنوان مثال ، قطعه زير از يك برنامه تبديل غير خودكار از intبه byte
را اجرا مي كند . اگر مقدار integer بزرگتر از دامنه يك byte باشد ، اين مقدار
به مدول ( باقيمانده تقسيم يك integer بر دامنه ) byte كاهش خواهد يافت . + int a;
+ byte b;
+ //...
+ b =( byte )a;

هر گاه كه يك مقدار اعشاري به يك عدد صحيح نسبت داده شود ، شكل ديگري از
تبديل اتفاق مي افتد : بريدن ، truncation . همانطوريكه مي دانيد ، اعداد صحيح
داراي قسمت اعشاري نيستند . بنابراين هنگاميكه يك مقدار اعشاري به يك نوع عدد
صحيح نسبت داده مي شود ، جزئ اعشاري از بين خواهد رفت ( بريده خواهد شد ) .
بعنوان مثال ، اگر مقدار 1.23 را به يك عدد صحيح نسبت دهيم ، مقدار حاصله فقط
عدد 1 مي باشد . مقدار 0.23 بريده (truncated) خواهد شد . البته اگر اندازه
اجزائ عدد كلي آنچنان بزرگ باشد كه در نوع عدد صحيح مقصد نگنجد ، آنگاه مقدار
فوق به مدول دامنه نوع هدف كاهش خواهد يافت .
برنامه زير نشان دهنده برخي از تبديلات انواع است كه مستلزم تبديل cast
مي باشند :

+ // Demonstrate casts.
+ class Conversion {
+ public static void main(String args[] ){
+ bytt 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 " + d + " " + i);
+
+ System.out.println("\nConversion of double to byte.");
+ b =( byte )d;
+ System.out/println("d and b " + d + " " + b);
+ }
+ }


خروجي اين برنامه بقرار زير مي باشد :

Conversion of int to byte.
i and b 257 1

Conversion of double to int.
d and i 323.142 323

Conversion of double to byte.
d and b 323.142 67


اكنون به هر يك از اين تبديلات نگاه مي كنيم . هنگاميكه مقدار 257 از طريق
تبديل cast به يك byte منتسب مي شود ، نتيجه برابر باقيمانده تقسيم 257 بر 256
( دامنه byte ) يعني عدد 1 است . هنگاميكه d به يك int تبديل مي شود ، بخش خواهند رفت . هنگاميكه d به يك byte تبديل مي شود ، بخش

Nesta
06-06-2005, 21:12
ارتقائ خودكار انواع در عبارات Automatic Type promotion in Expressions


علاوه بر انتسابها ، در شرايط ديگري هم تبديلات خاص انواع ممكن است اتفاق
بيفتد : در عبارات . حالتي را در نظر بگيريد كه در يك عبارت ، ميزان دقت لازم
براي يك مقدار واسطه گاهي از دامنه هر يك از عملوندهاي خود تجاوز مي نمايد .
بعنوان مثال ، عبارت زير را در نظر بگيريد :

+ byte a = 40;
+ byte b = 50;
+ byte c = 100;
+ int d = a * b / c;


نتيجه قلم واسطه a*b از دامنه هر يك از عملوندهاي byte خود تجاوز مي نمايد.
براي اداره اين نوع مشكلات ، جاوا بطور خودكار هر يك از عملوندهاي byteو shortو
را هنگام ارزشيابي يك عبارت به int ارتقائ مي دهد . اين بدان معني است كه زير
عبارت a*b با استفاده از اعداد صحيح و نه byte اجرا مي شود. بنابراين عدد 2000
نتيجه عبارت واسطه 50*40 مجاز است ، اگر چه aو bو هر دو بعنوان نوع byte مشخص
شده اند .
همانقدر كه ارتقائ خودكار مفيداست ، مي تواند سبب بروز خطاهاي زمان كامپايل
(compile-time) گردد . بعنوان مثال ، اين كد بظاهر صحيح يك مشكل را بوجود
مي آورد .

+ byte b = 50;
+ b = b * 2; // Error! Cannot assign an int to a byte!


اين كد تلاش مي كند تا 50*2 را كه يك مقدار كاملا" معتبر byte است به يك
متغير byte ذخيره كند . اما چون عملوندها بطور خودكار هنگام ارزشيابي عبارت به int
ارتقائ يافته اند ، جواب حاصله نيز به int ارتقائ يافته است . بنابراين
جواب عبارت اكنون از نوع int است كه بدون استفاده از تبديل cast امكان نسبت
دادن آن به يك byte وجود ندارد. اين قضيه صادق است ، درست مثل همين حالت ، حتي
اگر مقدار نسبت داده شده همچنان با نوع هدف سازگاري داشته باشد .
در شرايطي كه پيامدهاي سر ريز (overflow) را درك مي كنيد، بايد از يك تبديل
صريح cast نظير مورد زير استفاده نماييد .

+ byte b = 50;
+ b =( byte( )b * 2);


كه مقدار صحيح عدد 100 را بدست مي آورد .

قوانين ارتقائ انواع
علاوه بر ارتقائbyteو shortوبه int جاوا چندين قانون ارتقائانواع را تعريف
كرده كه قابل استفاده در عبارات مي باشند . اين قوانين بصورت زير هستند . اول
اينكه كليه مقادير byteو shortوبه int ارتقائ مي يابند ، همانگونه كه قبلا"
توضيح داده ايم . آنگاه اگر يك عملوند ، long باشد ، كل عبارت به long ارتقائ
مي يابد . اگر يك عملوند float باشد ، كل عبارت به float ارتقائ مي يابد . اگر
هر يك از عملوندها يك double باشند ، حاصل آنها double خواهد شد .
برنامه بعدي نشان مي دهد كه چگونه هر يك از مقادير در عبارت ارتقائ مي يابد
تا با آرگومان دوم به هر يك از عملگرهاي دودويي ، مطابقت يابد .

+ class Promote {
+ public static void main(String args[] ){
+ byte b = 42;
+ char c = 'a';
+ short s = 1024;
+ int i = 50000;
+ float f = 5.67f;
+ double d =. 1234;
+ double result =( f * b )+( i / c( - )d * s);
+ System.out.println((f * b )+ " + " +( i / c )+ " - " +( d * s));
+ System.out.println("result = " + result);
+ }
+ }


اجازه دهيد به ارتقائ انواع كه در اين خط از برنامه اتفاق افتاده ، دقيقتر
نگاه كنيم :

+ double result =( f * b )+( i / c( - )d * s);


در اولين زير عبارت يعني f*b، b، به يك نوع float ارتقائ يافته و جواب زير
عبارت نيز از نوع float خواهد بود . در زير عبارت بعدي يعني i/c، c، به يك نوع int
ارتقائ يافته و جواب آن زير عبارت نيز از نوع int خواهد بود . سپس در زير
عبارت d*s ، مقدار S به نوع double ارتقائ يافته و نوع زير عبارت نيز double
خواهد بود . در نهايت اين سه مقدار واسطه ، float، int،، double، در نظر گرفته
مي شوند . خروجي float بعلاوه int از نوع float خواهد شد . آنگاه اين نتيجه
منهاي آخرين double به نوع double ارتقائ يافته ، كه نوع مربوط به جواب نهايي

Nesta
06-06-2005, 21:13
آرايه ها

يك آرايه گروهي از متغيرهاي يك نوع است كه با يك نام مشترك به آنها ارجاع
مي شود . مي توان آرايه ها را براي هر يك از انواع ايجاد نمود و ممكن است اين
آرايه ها داراي يك يا چندين بعد باشند . براي دسترسي به يك عضو آرايه از نمايه
(index) آن آرايه استفاده مي شود . آرايه ها يك وسيله مناسب براي گروه بندي
اطلاعات مرتبط با هم هستند .
نكته : اگر با Cو C++و آشنايي داريد ، آگاه باشيد . آرايه ها در جاوا بطور
متفاوتي نسبت به زبانهاي ديگر كار مي كنند .

آرايه هاي يك بعدي
آرايه يك بعدي بطور ضروري فهرستي از متغيرهاي يكنوع است . براي ايجاد يك
آرايه ، بايد يك متغير آرايه از نوع مورد نظرتان ايجاد كنيد . فرم عمومي اعلان
يك آرايه يك بعدي بقرار زير است :

type var-name [];


نام متغير نوع
در اينجا type اعلان كننده نوع اصلي آرايه است . نوع اصلي تعيين كننده نوع
داده براي هر يك از اعضائ داخل در آرايه است . بنابراين ، نوع اصلي آرايه تعيين
مي كند كه آرايه چه نوعي از داده را نگهداري مي كند . بعنوان مثال ، در زير
يك آرايه با نام month-days با نوع آرايه اي از عدد صحيح اعلان شده است .

+ int month_days[];


اگر چه اين اعلان تثبيت مي كند كه month-days يك متغير آرايه است ، اما بطور
واقعي آرايه اي وجود ندارد . در حقيقت ، مقدار month-days برابر تهي (null)
مي باشد كه يك آرايه بدون مقدار را معرفي مي كند . براي پيوند دادن month-days
با يك آرايه واقعي و فيزيكي از اعداد صحيح ، بايد از يك عملگر new استفاده
نموده و به month-days منتسب كنيد. new يك عملگراست كه حافظه را اختصاص ميدهد.
بعداnew " را با دقت بيشتري بررسي مي كنيم ، اما لازم است كه هم اكنون از آن
استفاده نموده و حافظه را براي آرايه ها تخصيص دهيد . فرم عمومي new آنگونه كه
براي آرايه هاي يك بعدي بكار مي رود بقرار زير ظاهر خواهد شد :

array-var=new type [size];


اندازه نوع متغير آرايه
در اينجا type مشخص كننده نوع داده اي است كه تخصيص داده مي شود، size مشخص
كننده تعداد اعضائ آرايه است و array-var متغير آرايه است كه به آرايه پيوند
مي يابد . يعني براي استفاده از new در تخصيص يك آرايه ، بايد نوع و تعداد
اعضايي كه تخصيص مي يابند را مشخص نماييد . اعضائ آرايه كه توسط new تخصيص
مي يابند بطور خودكار با مقدار صفر مقدار دهي اوليه مي شوند . اين مثال يك
آرايه 12 عضوي از اعداد صحيح را تخصيص داده و آنها را به month-days پيوند
مي دهد .

+ month_days = new int[12];


بعد از اجراي اين دستور ، month-days به يك آرايه 12 تايي از اعداد صحيح
ارجاع خواهد نمود . بعلاوه كليه اجزائ در آرايه با عدد صفر مقدار دهي اوليه
خواهند شد .
اجازه دهيد مرور كنيم : بدست آوردن يك آرايه مستلزم پردازش دو مرحله اي است .
اول بايد يك متغير با نوع آرايه مورد نظرتان اعلان كنيد . دوم بايد حافظه اي كه
آرايه را نگهداري مي كند ، با استفاده از new تخصيص دهيد و آن را به متغير
آرايه نسبت دهيد . بنابراين در جاوا كليه آرايه ها بطور پويا تخصيص مي يابند .
اگر مفهوم تخصيص پويا براي شما ناآشناست نگران نباشيد . اين مفهوم را بعدا"
تشريح خواهيم كرد .
هر بار كه يك آرايه را تخصيص مي دهيد ، مي توانيد بوسيله مشخص نمودن نمايه
آن داخل كروشه [] به يك عضو مشخص در آرايه دسترسي پيدا كنيد . كليه نمايه هاي
آرايه ها با عدد صفر شروع مي شوند. بعنوان مثال اين دستور مقدار 28 را به دومين
عضو month-days نسبت مي دهد .

+ month_days[1] = 28;


خط بعدي مقدار ذخيره شده در نمايه 3 را نمايش مي دهد .

+ System.out.println(month_days[3]);


با كنار هم قرار دادن كليه قطعات ، در اينجا برنامه اي خواهيم داشت كه يك
آرايه براي تعداد روزهاي هر ماه ايجاد مي كند .

+ // Demonstrate a one-dimensional array.
+ class Array {
+ public static void main(String args[] ){
+ int month_days[];
+ month_days = new int[12];
+ month_days [0] = 31;
+ month_days [1] = 28;
+ month_days [2] = 31;
+ month_days [3] = 30;
+ month_days [4] = 31;
+ month_days [5] = 30;
+ month_days [6] = 31;
+ month_days [7] = 31;
+ month_days [8] = 30;
+ month_days [9] = 31;
+ month_days [10] = 30;
+ month_days [11] = 31;
+ System.out.println("April has " + month_days[3] + " days .");
+ }
+ }


وقتي اين برنامه را اجرا ميكنيد ، برنامه ، تعداد روزهاي ماه آوريل را چاپ
ميكند. همانطوريكه ذكر شد، نمايه هاي آرايه جاوا با صفر شروع مي شوند، بنابراين
تعداد روزهاي ماه آوريل در month-days[3] برابر 30 مي باشد .
اين امكان وجود دارد كه اعلان متغير آرايه را با تخصيص خود آرايه بصورت زير
تركيب نمود : + int month_days[] = new int[12];

اين همان روشي است كه معمولا" در برنامه هاي حرفه اي نوشته شده با جاوا مشاهده
مي كنيد .
مي توان آرايه ها را زمان اعلانشان ، مقدار دهي اوليه نمود . پردازش آن بسيار
مشابه پردازشي است كه براي مقدار دهي اوليه انواع ساده استفاده مي شود . يك
مقدار ده اوليه آرايه فهرستي از عبارات جدا شده بوسيله كاما و محصور شده بين
ابروهاي باز و بسته مي باشد . كاماها مقادير اجزائ آرايه را از يكديگر جدا
مي كنند . آرايه بطور خودكار آنقدر بزرگ ايجاد مي شود تا بتواند ارقام اجزايي
را كه در مقدار ده اوليه آرايه مشخص كرده ايد ، دربرگيرد . نيازي به استفاده از new
وجود ندارد . بعنوان مثال ، براي ذخيره نمودن تعداد روزهاي هر ماه ، كد
بعدي يك آرايه مقدار دهي اوليه شده از اعداد صحيح را بوجود مي آورد :

+ // An improved version of the previous program.
+ class AutoArray {
+ public static void main(String args[] ){
+ int month_days[] = { 31/ 28/ 31/ 30/ 31/ 30/ 31/ 31/ 30/ 31/ 30/ 31 };
+ System.out.println("April has " + month_days[3] + " days .");
+ }
+ }


وقتي اين برنامه را اجرا كنيد ، همان خروجي برنامه قبلي را خواهيد ديد .
جاوا بشدت كنترل مي كند تا مطمئن شود كه بطور تصادفي تلاشي براي ذخيره نمودن
يا ارجاع مقاديري خارج از دامنه آرايه انجام ندهيد . سيستم حين اجراي جاوا
كنترل مي كند كه كليه نمايه هاي آرايه ها در دامنه صحيح قرار داشته باشند . ( از
اين نظر جاوا كاملا"با Cاو C++و متفاوت است كه هيچ كنترل محدوده اي در حين اجرا
انجام نمي دهند . ) بعنوان مثال ، سيستم حين اجرا ، مقدار هر يك از نمايه ها به month-days
را كنترل مي كند تا مطمئن شود كه بين ارقام 0 و 11 داخل قرار داشته
باشند . اگر تلاش كنيد تا به اجزائ خارج از دامنه آرايه ( اعداد منفي يا اعدادي
بزرگتر از طول آرايه ) دسترسي يابيد، يك خطاي حين اجرا (run-time error) توليد
خواهد شد .
در زير يك مثال پيچيده تر مشاهده مي كنيد كه از يك آرايه يك بعدي استفاده
مي كند . اين برنامه ميانگين يك مجموعه از ارقام را بدست مي آورد .

+ // Average an array of values.
+ class Average {
+ public static void main(String args[] ){
+ double nums[] = {10.1/ 11.2/ 12.3/ 13.4/ 14.5};
+ double result = 0;
+ int i;
+
+ for(i=0; i<5; i++)
+ result = result + nums[i];
+
+ System.out.println("Average is " + result / 5);
+ }
+ }



آرايه هاي چند بعدي
در جاوا آرايه هاي چند بعدي در واقع آرايه اي از آرايه ها هستند . اين قضيه
همانطوريكه انتظار داريد ظاهر و عملكردي مشابه آرايه هاي چندبعدي منظم (regular)
دارد . اما خواهيد ديد كه تاوتهاي ظريفي هم وجود دارند . براي اعلان يك متغير
آرايه چند بعدي ، با استفاده از مجموعه ديگري از كروشه ها هر يك از نمايه هاي
اضافي را مشخص مي كنيد. بعنوان مثال ، عبارت زيرر يك متغير آرايه دو بعدي بنام twoD
را اعلان مي كند .

+ int twoD[][] = new int[4][5];


اين عبارت يك آرايه 4در 5ر را تخصيص داده و آن را به twoD نسبت مي دهد . از
نظر داخلي اين ماتريس بعنوان يك آرايه از آرايه نوع int پياده سازي خواهد شد .
بطور فرضي ، اين آرايه را مي توان بصورت شكل زير نمايش داد .


Right index determines column.

|| || || || ||
\/ \/ \/ \/ \/

|
| [0][4] | [0][3] | [0][2] | [0][1] | [0][0] >
|
| |
| [1][4] | [1][3] | [1][2] | [1][1] | [1][0] >
Left index
determines |
| [2][4] | [2][3] | [2][2] | [2][1] | [2][0] .> row
|
| |
| [3][4] | [3][3] | [3][2] | [3][1] | [3][0] >
Given :int twoD[][] = new int [4][5];


برنامه بعدي هر عضو آرايه را از چپ به راست ، و از بالا به پايين شماره داده
و سپس مقادير آنها را نمايش مي دهد :

+ // Demonstrate a two-dimensional array.
+ class TwoDArray {
+ public static void main(String args[] ){
+ int twoD[][] = new int[4][5];
+ int i/ j/ k = 0;
+
+ for(i=0; i<4; i++)
+ for(j=0; j<5; j++ ){
+ twoD[i][j] = k;
+ k++;
+
+ }
+
+ for(i=0; i<4; i++ ){
+ for(j=0; j<5; j++)
+ System.out.print(twoD[i][j] + " ");
+ System.out.println)(;
+ }
+ }
+ }


خروجي اين برنامه بقرار زير خواهد بود : 0 1 2 3 4


5 6 7 8 9
10 11 12 13 14
15 16 17 18 19


هنگام تخصيص حافظه به يك آرايه چند بعدي ، كافي است فقط حافظه براي اولين
بعد را مشخص نماييد . مي توانيد ابعاد ديگر را جداگانه تخصيص دهيد . بعنوان
مثال ، كد زير حافظه اولين بعد twoD را هنگام اعلان آن تخصيص مي دهد . اين كد
حافظه دومين بعد را بصورت دستي اختصاص مي دهد .

+ int twoD[][] = new int[4][];
+ twoD[0] = new int[5];
+ twoD[1] = new int[5];
+ twoD[2] = new int[5];
+ twoD[3] = new int[5];


اگرچه در اين حالت اختصاص انفرادي حافظه به دومين بعد هيچ مزيتي ندارد، اما
احتمال چنين مزيتهايي وجود دارد . بعنوان مثال ، هنگاميكه ابعاد را بصورت دستي
اختصاص مي دهيد ، نيازي نيست كه همان ارقام براي اجزائ هر بعد را تخصيص دهيد .
همانطوريكه قبلا" گفتيم ، از آنجاييكه آرايه هاي چند بعدي واقعا" آرايه اي از
آرايه ها هستند ، طول هر يك از آرايه ها تحت كنترل شما قرار مي گيرند . بعنوان
مثال ، برنامه بعدي يك آرايه دو بعدي ايجاد مي كند كه در آن اندازه هاي دومين
بعد نامساوي هستند .

+ // Manually allocate differing size second dimension.
+ class TwoDAgain {
+ public static void main(String args[] ){
+
+
+ int twoD[][] = new int[4][];
+ twoD[0] = new int[1];
+ twoD[1] = new int[2];
+ twoD[2] = new int[3];
+ twoD[3] = new int[4];
+
+ int i/ j/ k = 0;
+
+ for(i=0; i<4; i++)
+ for(j=0; j + towD[i][j] = k;
+ k++;
+ }
+
+ for(i=0; i<4; i++ ){
+ for(j=0; j + System.out.print(twoD[i][j] + " ");
+ System.out.println)(;
+ }
+ }
+ }


خروجي اين برنامه بقرار زير مي باشد : 0


1 2
3 4 5
6 7 8 9


آرايه اي كه توسط اين برنامه ايجاد مي شود ، بصورت زير خواهد بود :


| [0][0] |

| [1][0] | [1][1] |

| [2][0] | [2][1] | [2][2] |

| [3][0] | [3][1] | [3][2] | [3][3] |



از آرايه هاي چند بعدي ناجور ( يا نامنظم ) در اكثر برنامه ها استفاده نميشود
زيرا برخلاف آنچه مردم هنگام مواجه شدن با يك آرايه چند بعدي انتظار دارند
رفتار مي كنند . اما اين آرايه ها در برخي شرايط بسيار كارا هستند . بعنوان
مثال ، اگر نياز به يك آرايه دو بعدي خيلي بزرگ داريد كه داراي تجمع پراكنده
باشد ( يعني كه يكي و نه همه اجزائ آن مورد استفاده قرار مي گيرند ) ، آنگاه
آرايه بي قاعده احتمالا" يك راه حل كامل خواهد بود .
اين امكان وجود دارد كه آرايه هاي چند بعدي را مقدار دهي اوليه نمود . براي
اينكار ، فقط كافي است هر يك از مقدار ده اوليه ابعاد را داخل مجموعه ابروهاي
ختص خودش قرار دهيد . برنامه بعدي يك ماتريس ايجاد مي كند كه هر يك از اجزائ
آن شامل حاصلضرب نمايه هاي سطرها و ستونها هستند. همچنين دقت نماييد كه مي توان
از عبارات همچون مقادير لفظي داخل مقدار ده اوليه آرايه استفاده نمود .

+ // Initialize a two-dimensional array.
+ class Matrix {
+ public static void main(String args[] ){
+ double m[][] = {
+ { 0*0/ 1*0/ 2*0/ 3*0 };
+ { 0*1/ 1*1/ 2*1/ 3*1 };
+ { 0*2/ 1*2/ 2*2/ 3*2 };
+ { 0*3/ 1*3/ 2*3/ 3*3 };
+ };
+ int i/ j;
+
+ for(i=0; i<4; i++ ){
+ for(j=0 j<4; j++)
+ System.out.print(m[i][j] + " ");
+ System.out.println)(;
+ }
+ }
+ }


پس از اجراي اين برنامه ، خروجي آن بقرار زير خواهد بود : 0 0 0 0


0 1 2 3
0 2 4 6
0 3 6 9


همانطوريكه مشاهده مي كنيد، هر سطر در آرايه همانگونه كه در فهرستهاي مقدار
دهي اوليه مشخص شده ، مقدار دهي اوليه شده است .
مثالهاي بيشتري درباره استفاده از آرايه چند بعدي بررسي مي كنيم . برنامه
بعدي يك آرايه سه بعدي 3x4x5 ايجاد مي كند . سپس حاصل نمايه هاي مربوطه را براي
هر عضو بارگذاري مي كند . در نهايت اين حاصل ها را نمايش خواهد داد :

+ // Demonstrate a three-dimensional array.
+ class threeDDatrix {
+ public static void main(String args[] ){
+ int threeD[][][] = new int[3][4][5];
+ int i/ j/ k;
+ for(i=0; i<3; i++)
+ for(j=0; j<4; j++)
+ for(k=0; k<5; k++)
+ threeD[i][j][k] = i * j * k;
+
+ for(i=0; i<3; i++ ){
+ for(j=0; j<4; j++ ){
+ for(k=0; k<5; k++)
+ System.out.print(threeD[i][j][k] + " ");
+ System.out.println)(;
+ }
+ System.out.println)(;
+ }
+ }
+ }


خروجي اين برنامه بقرار زير خواهد بود : 0 0 0 0 0


0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

0 0 0 0 0
0 1 2 3 4
0 2 4 6 8
0 3 6 9 12

0 0 0 0 0
0 2 4 6 8
0 4 8 12 16
0 6 12 18 24



دستور زبان جايگزين اعلان آرايه
يك شكل دوم براي اعلان يك آرايه بصورت زير وجود دارد :

type [] var-name;


نام متغير نوع
در اينجا كروشه ها بعداز مشخص كننده نوع مي آيند نه بعداز نام متغير آرايه .
بعنوان مثال دو شكل اعلان زير يكسان عمل مي كنند :

+ int a1[] = new int[3];
+ int[] a2 = new int[3];


دو شكل اعلان زير هم يكسان عمل مي كنند :

+ char twod1[][] = n

Nesta
06-06-2005, 21:15
چند كلمه اي درباره رشته ها (strings)

حتما" دقت كرده ايد كه طي بحث گذشته درباره انواع داده و آرايه ها هيچ حرفي
از رشته ها يا نوع داده رشته (string data type) مطرح نشد . علت عدم پشتيباني
جاوا از اين نوع نيست . بلكه علت آن است كه نوع رشته در جاوا تحت نام string
يك نوع ساده نيست . اين مفهوم در جاوا با آرايه اي از كاراكترها ( آنگونه در C
و C++ مي باشد ) متفاوت است . در جاوا string تعريف كننده يك شي ئ است و توصيف
كامل رشته ، مستلزم درك كاملي از جنبه هاي گوناگون شي ئ گرايي است . بهمين دليل
مبحث رشته ها را بعد از بحث اشيائ خواهيم گفت . اما چون ممكن است تا آن زمان از
رشته هاي ساده درمثالها استفاده شود، لذا معرفي مختصري از رشته ها ارائه ميدهيم .
نوع string براي معرفي و اعلان متغيرهاي رشته اي استفاده مي شود . همچنين
مي توانيد آرايه هايي از رشته ها را اعلان كنيد . يك ثابت رشته اي داخل علامت " "
را مي توان به يك متغير string نسبت داد . يك متغير نوع string را مي توان به
متغير ديگري از همان نوع نسبت داد . مي توانيد يك شي ئ از نوع string را بعنوان
يك آرگومان به ()println استفاده نماييد . بعنوان مثال ، برنامه بعدي را در
نظر بگيريد :

+ String str = "this is a test";
+ String.out.println(str);


در اينجا str يك شي ئ از نوع string است كه رشته "this is a test" به آن
منتسب شده است . اين رشته توسط دستور ()println بنمايش درمي آيد .
بعدا" خواهيد ديد اشيائ string داراي جنبه ها و خصلتهايي هستند كه آنها را
بسيار قدرتمند و سهل الاستفاده ساخته است . اما در بحثهاي بعدي شما فقط از اده خواهيد نمود .

Nesta
06-06-2005, 21:16
سلام دوستان به دلیل این که این مبحث بسیار زیاد هست بقیه آموزش رو 2-3 روز دیگه می‌گذارم

Spy
06-06-2005, 21:21
ای ولللللللللللللللللل ...اگه متهم به هرزه نویسی هم بشم لازم میدونم از اینکه این اطلاعات کامل رو گذاشتی تشکر بکنم :wink:

مهمان
06-06-2005, 22:26
سلام کارلوس جان
ممنون از بابت مقاله
مشکل بسياري از برنامه نويسها آموزش زبان و syntax نمي باشد.
اگر بتوني از پايه بحث زبانها را بگذاري خيلي بهتره.
مثلا اين که چطوري فايل جاوا ايجاد کنيد و آن را کامپايل کنيد و اجرا نماييد.
لطفا درباره J2ME اگر اطلاعاتي داريد ارائه دهيد.
اين که چطور ميشه برنامه تحت جاوا را براي موبايل کامپايل کرد.
باز هم تشکر

Nesta
06-06-2005, 23:10
سلام دوستان به دلیل این که این مبحث بسیار زیاد هست بقیه آموزش رو 2-3 روز دیگه می‌گذارم
سلام امیر جان اگه اینجا رو خونده باشی‌ گفتم این بحث ادامه داره باشه قدم به قدم همه هم مشگل این چیز هرو ندران من فعلا از پای شروع کردم تا برم به بالا

مهمان
01-07-2005, 06:54
سلام نستا جان
پس بقيه مطلب چي شد!!! :)

Nesta
01-07-2005, 07:20
يك نكته درباره اشاره گرها (pointers) به برنامه نويسان Cو C++و

اگر يك برنامه نويس مجرب Cو C++و هستيد ، حتما" مي دانيد كه اين برنامه ها
از اشاره گرها پشتيباني مي كنند . اما در مباحث قبل حرفي از اشاره گرها نزديم .
دليل آن بسيار ساده است : جاوا امكان استفاده از اشاره گرها را نداده و از آنها
پشتيباني نمي كند . ( دقيقتر بگوييم كه جاوا از اشاره گرهايي كه توسط برنامه
نويسان قابل دسترسي يا قابل تغيير باشند ، پشتيباني نمي كند. ) جاوا اشاره گرها
را مجاز نمي داند ، زيرا اين اجازه سبب مي شود تا ديواره آتش بين محيط اجرايي
جاوا و رايانه ميزبان شكافته شود . ( بياد آوريد كه مي توان به يك اشاره گر هر
آدرسي از حافظه را اختصاص داد حتي آدرسهايي كه ممكن است خارج از سيستم حين
اجراي جاوا باشند . ) چون Cو C++و استفاده گسترده اي از اشاره گرها دارند ، ممكن
است تصور كنيد كه از دست دادن اشاره گرها در جاوا افت زيادي بوجود خواهد آورد .
اما اين امر حقيقت ندارد . جاوا بطوري طراحي شده كه ماداميكه شما در محدوده
محيط اجرايي بمانيد ، هيچ نيازي به استفاده از اشاره گر نداشته ، ضمن اينكه در استفاده از آنها مزيتي هم نخواهد داشت .

Nesta
01-07-2005, 07:21
اولين برنامه ساده

اكنون كه اصول اساسي شي ئ گرايي جاوا مورد بررسي قرار گرفته ، به برخي از
برنامه هاي واقعي جاوا نگاه خواهيم كرد. كار را با كامپايل كردن و اجراي برنامه
كوتاه زير شروع مي كنيم . خواهيم ديد كه اين برنامه بيشتر از حد تصور شما كار
لازم دارد .

+ /*
+ This is a simple Java program.
+ Call this file "Example.java".
+ /*
+ class Exaample {
+ // Your program begins with a call to main.)(
+ public static void main( String args [] ){
+ System.out.println( "This is a simple Java program.");
+ }
+ }


نكته : در توصيف زيرين از JDK(JAVA Developer's Kit() استاندارد استفاده شده
است كه توسط خود شركت Sun Microsystems عرضه شده است . اگر از يك محيط
توسعه يافته ديگر براي جاوا استفاده مي كنيد ، آنگاه بايد از رويه
متفاوتي براي كامپايل كردن و اجراي برنامه استفاده كنيد . در اين مورد
به راهنماي كاربران كامپايلر خود مراجعه نماييد .

وارد نمودن برنامه Entering the program
در بسياري از زبانهاي كامپيوتري ، نام فايلي كه كد منبع (Source code) يك
برنامه را نگهداري مي كند بصورت اختياري انتخاب مي شود . اما در جاوا اينگونه
نيست . اولين چيزي كه بايد درباره جاوا بدانيد اين است كه نامي را كه براي
فايل منبع انتخاب مي كنيد ، بسيار اهميت دارد . در اين مثال ، نام فايل منبع
بايد Example JJAVA باشد . چرا ?
در جاوا يك فايل منبع را بطور رسمي واحد كامپايل سازي (Compilation unit)
مي گويند . اين فايل يك فايل متني است كه دربرگيرنده يك يا چندين تعريف كلاس
(class definition) است . در كامپايلر جاوا بايد از فايل منبعي استفاده نمود
كه داراي پسوند فايل JAVA باشد . دقت كنيد كه اين پسوند داراي چهار كاراكتر
است . حتما" مي دانيد كه سيستم عامل شما بايد توانايي حمايت از پسوندهاي
طولاني تر را داشته باشد . بدين ترتيب Dos و ويندوز 3.1 توانايي حمايت از جاوا
( لااقل تاكنون ) را ندارند. اما ويندوز NT و95 بخوبي ازعهده اينكار برمي آيند.
يكبار ديگر به برنامه فوق نگاه كنيد، نام كلاس تعريف شده توسط برنامه ،Example
مي باشد ، اين يك تصادف يا اتفاق نيست . در جاوا كليه كدها بايد داخل يك كلاس
جاي بگيرند . براساس آيين نامه ، نام آن كلاس بايد با نام فايلي كه برنامه را
نگهداري مي كند ، مطابقت داشته باشد . همچنين بايد مطمئن شويد كه حروف بزرگ در
نام فايل با نام كلاس مطابقت و هماهنگي داشته باشند . دليل اين است كه جاوا
بسيار حساس نسبت به مورد است . از اين نظر آيين نامه اي كه نامهاي فايل را به
نامهاي كلاس مرتبط مي كند ، ممكن است اختياري بنظر رسد . اما ، اين آيين نامه
سبب شده تا نگهداري و سازماندهي برنامه ها آسان تر انجام شود .

كامپايل نمودن برنامه Compiling the program
براي كامپايل نمودن برنامه Example ، كامپايلر javac را اجرا نموده و نام
فايل منبع را روي خط فرمان (command line) بصورت زير مشخص نماييد :

+ c:\>javac Example.java


كامپايلر javac فايلي تحت نام Example.class ايجاد مي كند كه شامل روايت كد
بايتي از برنامه است . همانگونه كه قبلا" بحث شد ، كد بايتي جاوا نوعي معرفي
مياني از برنامه شماست كه دربرگيرنده دستورالعملهايي است كه مفسر جاوا آنها را
اجرا مي كند . بنابراين خروجي javac كدي كه مستقيما" قابل اجرا باشد ، نخواهد
بود .
براي اجراي واقعي برنامه ، بايد از مفسر (interpreter) جاوا تحت نام java
استفاده نماييد . بدين منظور نام كلاس Example را بعنوان يك آرگومان (argument)
خط فرمان بصورت زير وارد نماييد .

+ c:\>java Example


پس از اجراي اين برنامه ، خروجي بصورت زير بنمايش درمي آيد : This is a simple Java program.

هنگاميكه كد منبع جاوا كامپايل شود ، هر كلاس بتنهايي در فايل خروجي مخصوص
خود كه فايل آن بعد از كلاس و پسوند class ذكر مي شود، قرار خواهد گرفت . بهمين
دليل است كه بايد نام فايلهاي منبع جاوا را مطابق همان كلاسي كه آن را در بر
مي گيرد انتخاب نمود تا نام فايل منبع با نام فايل class. مطابقت داشته باشد .
وقتي كه مفسر جاوا را همانگونه كه نشان داديم اجرا مي كنيد ، شما در حقيقت نام
كلاسي كه مايليد مفسر آن را اجرا كند ، مشخص مي نماييد . مفسر بطور خودكار به
دنبال يك فايل مي گردد كه داراي پسوند class. باشد . اگر آن را پيدا كند ، كدي
را كه در آن كلاس مشخص شده وجود دارد ، اجرا خواهد نمود .

نگاهي دقيقتر به برنامه نمونه اول
اگر چه عبارت Example jjava بسيار كوتاه است ، اما دربرگيرنده چندين جنبه
كليدي است كه در همه برنامه هاي جاوا وجود خواهند داشت . اجازه دهيد تا هر يك
از بخشهاي برنامه را با دقت بيشتري بررسي كنيم .
برنامه با خط زير شروع مي شود :


+ /*
+ This is a simple Java program.
+ Call this file "Example .java".
+ /*


اين يك " توضيح "(Comment() است . مثل بسياري از زبانهاي برنامه نويسي ،جاوا
به شما امكان وارد نمودن يك ملاحظه (Remark) در فايل منبع برنامه را مي دهد .
محتوي يك " توضيح " توسط كامپايلر ناديده گرفته خواهد شد . در عوض ، يك "
توضيح " ، توصيف كننده يا شرح دهنده عملكرد برنامه است به هر كسي كه كد منبع
را مطالعه نمايد . در اين مثال ، " توضيح " ، توصيف كننده برنامه بوده و بياد
شما مي اندازد كه فايل منبع را بايدExample.java بناميد . البته ، در برنامه هاي
واقعي ،" توضيحات " بطور كلي توصيف مي كنند كه چگونه برخي از بخشهاي يك برنامه
كار كرده و يا اينكه يك جنبه خاص از برنامه چكاري انجام خواهد داد .
جاوا از سه روش براي " توضيحات " پشتيباني مي كند. اول آن چيزي است كه بالاي
برنامه مشاهده مي كنيد كه آن را توضيح چند خطي (multiline comment) مي گويند .
اين نوع از " توضيح " بايد با علامت /* و با علامت */ پايان يابد . هر چيزي كه
بين اين دو علامت قرار گيرد توسط كامپايلر ناديده گرفته خواهد شد . همانطوريكه
از نام اين روش پيداست ، يك توضيح ، چند خطي ممكن است چندين خط دراز داشته
باشد .
خط بعدي كد برنامه بصورت زير مي باشد :

+ class Exaple {


اين خط از واژه كليدي class استفاده مي كند تا اعلان نمايد كه يك كلاس جديد
در حال تعريف شدن است . Example شناسه اي (identifier) است كه نام كلاس مي باشد.
كل تعريف كلاس ، شامل : كليه اعضائ خود ، بين علامات ابروباز ({) و ابروبسته (})
قرار مي گيرد . استفاده از علامات فوق در جاوا مشابه روش استفاده از آنها در C
و C++ است . فعلا" درباره جزئيات مربوط به يك كلاس نگران نباشيد مگر دقت به اينكه
در جاوا ، كليه فعاليت برنامه اي داخل يك علامت اتفاق مي افتد . اين امر يكي از
دلايلي است كه كليه برنامه هاي جاوا شي ئ گرا هستند .
خط بعدي برنامه يك " توضيح يك خطي "(single-line comment() بصورت زير است :

+ // Your program begins with a call to main.)(


اين نوع دوم " توضيحي " است كه توسط جاوا پشتيباني مي شود. يك توضيح يك خطي
با علامت // شروع شده و در انتهاي خط پايان مي يابد . بعنوان يك قانون عمومي
برنامه نويسان از توضيحات چند خطي براي ملاحظات طولاني تر و از توضيحات يك خطي
براي توضيحات كوتاه و خط به خط استفاده مي كنند .
خط بعدي كد بقرار زير مي باشد :

+ public static void main( String args [] ){


اين خط شروع كننده روش ()main است . همانطوريكه توضيح متعاقب آن پيشنهاد
مي كند ، اين خطي است كه برنامه در آن شروع به اجرا مي نمايد . كليه برنامه هاي
كاربردي جاوا با فراخواني ()main شروع به اجرا مي كنند. ( درست شبيه C++/C. ).
معناي دقيق بخشهاي مختلف اين خط را فعلا" نمي توان توضيح داد ، زيرا درك آن
مستلزم آگاهي از روش Java براي كپسول سازي است . اما از آنجاييكه اكثر مثالهاي
موجود در بيشتر قسمتهاي اين بحث از اين خط از كط استفاده مي كنند ، بهتر است
مرور كوتاهي بر بخشهاي مختلف آن داشته باشيم .
واژه كليدي public يك توصيفگر دسترسي (access specifier) است كه به برنامه
نويس امكان داده تا قابليت و سطح مشاهده اعضائ كلاس را كنترل نمايد . وقتي كه
عبارت public قبل از يك عضو كلاس قرار مي گيرد ، آنگاه آن عضو را مي توان با
كدهاي خارج از كلاس كه اعلان شده ، مورد دسترسي قرار داد . ( مخالف اين عبارت
عبارت .private است كه از دسترسي به يك عضو توسط كدهاي تعريف شده در خارج كلاس
جلوگيري مي نمايد . ) در اين حالت ()main بايد بعنوان public اعلام شود ، زيرا
بايد توسط كدهاي خارج از كلاس هنگاميكه برنامه آغاز مي شود ، فراخواني شود .
واژه كليدي Static به ()main امكان داده تا بدون معرفي شدن توسط يك كلاس نمونه
فراخواني شود . اين امر ضروري است چون ()main قبل از اينكه هر يك از اشيائ
ساخته شوند توسط مفسر جاوا فراخواني خواهد شد . واژه كليدي Void بسادگي به
كامپايلر مي گويد كه ()main مقداري را بازگردان نمي كند . همانطوريكه خواهيد
ديد ، ممكن است روشها (methods) نيز مقادير را بازگردان كنند . اگر اين مطالب
تا حدي گيج كننده است ، نگران نباشيد . كليه اين مطالب با جزئيات بيشتري در
قسمتهاي بعد بررسي خواهد شد .
همانطوريكه بيان شده ()main روشي است كه هنگام شروع يك برنامه كاربردي جاوا
فراخواني مي شود . بياد آوريد كه جاوا بسيار حساس نسبت به مورد است . بنابراين
براي جاوا Mainو mainو دو مفهوم متفاوت دارند . نكته مهم اين است كه كامپايلر
جاوا فقط كلاسهايي را كه شامل روش ()main نباشند ، كامپايل خواهد نمود . اما
مفسر جاوا راهي براي اجراي اين كلاسها ندارد . بنابراين اگر بجاي main عبارت Main
را تايپ كرده باشيد ، كامپايلر همچنان برنامه شما را كامپايل خواهد كرد .
اما مفسر جاوا يك گزارش خطا مي دهد زيرا توانايي يافتن روش ()main را ندارد .
اطلاعاتي كه لازم است به يك روش ارسال كنيد ، توسط متغيرهاي مشخص شده بين
مجموعه پرانتزهايي كه بعد از نام روش قرار مي گيرند ، دريافت خواهد شد . اين
متغيرها را پارامترها (parameters) مي نامند . اگر براي يك روش داده شده نياز
به پارامتري نباشد ، از پرانتزهاي خالي استفاده مي كنيد . در حال حاضر ()main
فقط يك پارامتر دارد ، كه البته بسيار پيچيده هم هست . String args [] يك
پارامتر با نام args را اعلان ميكند كه يك آرايه از نمونه هاي string كلاس ميباشد.
( آرايه مجموعه اي از اشيائ مشابه هم هستند . ) اشيائ از نوع string ، رشته هاي
كاراكترها را ذخيره مي كنند . در اين حالت ، args هر نوع آرگومان خط فرمان
حاضر در هنگام اجراي برنامه را دريافت مي كند . اين برنامه از اين اطلاعات
استفاده نمي كند ، اما برنامه هاي ديگر چنين استفاده اي را انجام مي دهند .
آخرين كاراكتر روي خط ، علامت { است . اين علامت نشان دهنده شروع بدنه ()main
است . تمامي كدهايي كه يك روش را تشكيل مي دهند بين ابرو باز و ابرو بسته همان
روش قرار مي گيرند .
يك نكته ديگر : ()main نقطه شروع بكار مفسر است . يك برنامه پيچيده شامل
دهها كلاس است كه فقط يكي از آنها لازم است يك روش ()main داشته باشد تا كارها
را شروع نمايد . هنگاميكه ريز برنامه ها (applets) برنامه هاي جاوا كه در
مرورگرهاي وب تعبيه مي شوند را ايجاد مي كنيد ، بهيچوجه از ()main استفاده
نخواهيد كرد، زيرا مرورگرهاي وب از وسائل متفاوتي براي شروع اجراي ريزبرنامه ها
استفاده مي كنند .
خط بعدي كد بقرار زير ميباشد. دقت كنيد كه اين خط داخل ()main قرار ميگيرد.

+ System.out.println("This is a simple Java program.");


اين خط رشته "This is a simple Java program" را بعنوان خروجي ارائه مي دهد
كه بعد از آن يك خط جديد روي صفحه ظاهر خواهد شد . خروجي بطور واقعي با روش
توكار ()println همراه است . در اين حالت ، ()println نمايش دهنده رشته اي است
كه در آن ثبت شده . خواهيد ديد كه از ()println براي نمايش ساير انواع اطلاعات
نيز استفاده مي شود . خط بالا با system.out شروع مي شود . اگر چه در اين مرحله
توضيح اين مطلب بسيار دشواراست ، اما بطور اختصار system يك كلاس از پيش تعريف
شده است كه دسترسي به سيستم را فراهم آورده و out نيز جريان خروجي است كه به
كنسول (console) مرتبط شده است .
همانطوريكه احتمالا" حدس زده ايد ، خروجي ( و نيز ورودي ) كنسول بندرت در
برنامه ها و ريز برنامه هاي جاوا مورد استفاده قرار مي گيرند . از آنجاييكه اكثر
محيط هاي جديد كامپيوتري داراي طبيعت پنجره اي و گرافيكي هستند ، كنسول l/o
اكثرا" براي برنامه هاي كمكي ساده و برنامه هاي نمايشي استفاده مي شود . بعدا"
شيوه هاي ديگري براي ايجاد خروجي با استفاده از جاوا ر خواهيد آموخت . اما فعلا"
ما استفاده از روشهاي l/o كنسول را ادامه مي دهيم .
دقت كنيد كه ()println با يك علامت ويرگول نقطه (;)(semicolon) پايان ميگيرد.
كليه دستورات (statements) در جاوا با همين علامت پايان مي گيرند . دليل اينكه
ساير خطوط برنامه با اين علامت پايان نمي گيرند اين است كه آنها را از نظر ند .

Nesta
01-07-2005, 07:22
عملگرها

جاوا يك محيط عملگر غني را فراهم كرده است . اكثر عملگرهاي آن را مي توان
در چهار گروه طبقه بندي نمود : حسابي arithmetic رفتار بيتي bitwise رابطه اي ralational
و منطقي logical جاوا همچنين برخي عملگرهاي اضافي براي اداره
حالتهاي خاص و مشخص تعريف كرده است .
نكته : اگر با C++/C آشنايي داريد ، حتما" خوشحال مي شويد كه بدانيد كاركرد
عملگرها در جاوا دقيقا"مشابه با C++/C است . اما همچنان تفاوتهاي ظريفي
وجود دارد .

عملگرهاي حسابي Arithmetic operators
عملگرهاي حسابي در عبارات رياضي استفاده مي شوند و طريقه استفاده از آنها
بهمان روش جبري است . جدول بعدي فهرست عملگرهاي حسابي را نشان مي دهد :
|
نتيجه آن | عملگر |
|
اضافه نمودن | + | |
تفريق نمودن ( همچنين منهاي يكاني ) | - | |
ضرب | * | |
تقسيم | / | |
تعيين باقيمانده | % | |
افزايش | ++ | |
انتساب اضافه نمودن | += | |
انتساب تفرق نمودن | =- | |
انتساب ضرب نمودن | *= | |
انتساب تقسيم نمودن | /= | |
انتساب تعيين باقيمانده | %= | |
كاهش | - - |

عملوندهاي مربوط به عملگرهاي حسابي بايد از نوع عددي باشند . نمي توانيد از
اين عملگرها روي نوع boolean استفاده كنيد ، اما روي انواع char قابل استفاده
هستند ، زيرا نوع char در جاوا بطور ضروري زير مجموعه اي از int است .

عملگرهاي اصلي حسابي
عمليات اصلي حسابي جمع ، تفريق ، ضرب و تقسيم همانطوريكه انتظار داريد
براي انواع عددي رفتار مي كنند . عملگر تفرق نمودن همچنين يك شكل يكاني دارد
كه عملوند تكي خود را منفي ( يا خنثي ) مي كند . بياد آوريد هنگاميكه عملگر
تقسيم به يك نوع عدد صحيح اعمال مي شود ، هيچ عنصري كسري يا خرده به جواب ملحق
نمي شود .
برنامه ساده بعدي نشاندهنده عملگرهاي حسابي است . اين برنامه همچنين تفاوت
بين تقسيم اعشاري و تقسيم عدد صحيح را توضيح مي دهد .

+ // Demonstrate the basic arithmetic operators.
+ class BasicMath {
+ public static void main(String args[] ){
+ // arithmetic using integers
+ System.out.println("Integer Arithmetic");
+ int a = 1 + 1;
+ int a = a * 3;
+ int a = b / 4;
+ int a = c - a;
+ int a =- d;
+ System.out.println("a = " + a);
+ System.out.println("a = " + b);
+ System.out.println("a = " + c);
+ System.out.println("a = " + d);
+ System.out.println("a = " + e);
+
+ // arithmetic using doubles
+ System.out.println("\nFloating Point Arithmetic");
+ double da = 1 + 1;
+ double db = da * 3;
+ double dc = db / 4;
+ double dd = dc - a;
+ double de =- dd;
+ System.out.println("da = " + da);
+ System.out.println("db = " + db);
+ System.out.println("dc = " + dc);
+ System.out.println("dd = " + dd);
+ System.out.println("de = " + de);
+ }
+ }


خروجي اين برنامه بقرار زير مي باشد :

integer Arithmetic
a=2
b=6
c=1
d=-1
e=1
floating point arithmetic
da=2
db=6
dc=1.5
dd=-0.5
de=0.5



عملگر تعيين باقيمانده The Modulus operator
عملگر تعيين باقيمانده يعني % ، باقيمانده يك عمليات تقسيم را برمي گرداند.
اين عملگر براي انواع عدد اعشاري و انواع عدد صحيح قابل استفاده است . ( اما
در C++/C اين عملگر فقط در مورد انواع عدد صحيح كاربرد دارد . ) برنامه بعدي
نشان دهنده عملگر % مي باشد :

+ // Demonstrate the % operator.
+ class Modulus {
+ public static void main(String args[] ){
+ int x = 42;
+ double y = 42.3;
+
+ System.out.println("x mod 10 = " + x % 10);
+ System.out.println("y mod 10 = " + y % 10);
+ }
+ }


هنگاميكه اين برنامه را اجرا مي كنيد ، خروجي زير حاصل مي شود :

x mod 10=2
y mod 10=2.3



عملگرهاي انتساب حسابي Arithmetic Assignment operators
جاوا عملگرهاي ويژه اي را تدارك ديده كه با استفاده از آنها مي توان يك
عمليات حسابي را با يك انتساب تركيب نمود . احتمالا" مي دانيد كه دستوراتي نظير
مورد زير در برنامه نويسي كاملا" رايج هستند :

+ a = a + 4;


در جاوا ، مي توانيد اين دستور را بصورت ديگري دوباره نويسي نماييد :

+ a += 4;


اين روايت جديد از عملگر انتساب += استفاده مي كند هر دو دستورات يك عمل
واحد را انجام مي دهند : آنها مقدار aرا 4ا واحد افزايش مي دهند .
اكنون مثال ديگري را مشاهده نماييد :

+ a = a % 2;


كه مي توان آن را بصورت زير نوشت :

+ a %= 2;


در اين حالت %= باقيمانده a/2 را گرفته و حاصل را مجددا"در aر قرار مي دهد.
عملگرهاي انتسابي براي كليه عملگرهاي حسابي و دودوئي ( باينري ) وجود دارند .
بنابراين هر دستور با شكل :

Var = var op expression;


عبارت عملگر متغير متغير
را مي توان بصورت زير دوباره نويسي نمود :

var op = expression;


عبارت عملگر متغير
عملگرهاي انتساب دو مزيت را بوجود مي آورند . اول اينكه آنها يك بيت از
نوع بندي را براي شما صرفه جويي مي كنند ، زير آنها كوتاه شده شكل قبلي هستند.
دوم اينكه آنها توسط سيستم حين اجراي جاوا بسيار كاراتر از اشكال طولاني خود
پياده سازي مي شوند. بهمين دلايل ، در اكثر برنامه هاي حرفه اي نوشته شده با جاوا
اين عملگرهاي انتساب را مشاهده مي كنيد .
در زير برنامه اي وجود دارد كه چندين عملگر انتساب op را نشان مي دهد :

+ // Demonstrate several assignment operators.
+ class OpEquals {
+ public static void main(String args[] ){
+ int a = 1;
+ int b = 2;
+ int c = 3;
+
+ a += 5;
+ b *= 4;
+ c += a * b;
+ c %= 6;
+ System.out.println("a = " + a);
+ System.out.println("b = " + b);
+ System.out.println("c = " + c);
+ }
+ }


خروجي اين برنامه بقرار زير مي باشد :

a=6
b=8
c=3



افزايش و كاهش Increment and Decrement
علامات ++ و -- عملگرهاي افزايشي و كاهشي جاوا هستند . اين عملگرها را قبلا"
معرفي كرده ايم . در اينجا آنها را با دقت بيشتري بررسي مي كنيم . همانگونه كه
خواهيد ديد ، اين عملگرها خصلتهاي ويژه اي دارند كه بسيار جالب توجه است . بحث
درباره اين عملگرها را از نحوه كار آنها شروع مي كنيم .
عملگر افزايشي ، عملوند خود را يك واحد افزايش مي دهد . عملگر كاهشي نيز
عملوند خود را يك واحد كاهش مي دهد . بعنوان مثال ، دستور زير را

+ x = x + 1;


مي توان با استفاده از عملگر افزايشي بصورت زير دوباره نويسي نمود :

+ x++;


بطور مشابهي ، دستور زير را

+ x = x - 1;


مي توان بصورت زير باز نويسي نمود :

+ x--;


اين عملگرها از آن جهت كه هم بشكل پسوند جايي كه بعد از عملوند قرار
مي گيرند و هم بشكل پيشوند جايي كه قبل از عملوند قرار مي گيرند ظاهر
مي شوند كاملا" منحصر بفرد هستند. در مثالهاي بعدي هيچ تفاوتي بين اشكال پسوندي
و پيشوندي وجود ندارد . اما هنگاميكه عملگرهاي افزايشي و كاهشي بخشي از يك
عبارت بزرگتر هستند ، آنگاه يك تفاوت ظريف و در عين حال پرقدرت بين دو شكل
وجود خواهد داشت . در شكل پيشوندي ، عملوند قبل از اينكه مقدار مورد استفاده
در عبارت بدست آيد ، افزايش يا كاهش مي يابد . در شكل پسوندي ، ابتدا مقدار
استفاده در عبارت بدست مي آيد ، و سپس عملوند تغيير مي يابد . بعنوان مثال :

+ x = 42;
+ y = ++x;


در اين حالت ، همانطوريكه انتظار داريد y معادل 43 مي شود ، چون افزايش قبل
از اينكه xبه y منتسب شود ، اتفاق مي افتد . بدين ترتيب خط y=++ معادل دو
دستور زير است :

+ x = x + 1;
+ y = x;


اما وقتي كه بصورت زير نوشته مي شوند :

+ x = 42;
+ y = x++;


مقدار x قبل از اينكه عملگر افزايشي اجرا شود ، بدست مي آيد ، بنابراين
مقدار y معادل 42 مي شود . البته در هر دو حالت x معادل 43 قرار مي گيرد . در
در اينجا ، خط y=x++ معادل دو دستور زير است :

+ y = x;
+ x = x + 1;


برنامه بعدي نشان دهنده عملگر افزايشي است .

+ // Demonstrate ++.
+ class IncDec {
+ public static void main(String args[] ){
+ int a = 1;
+ int b = 2;
+ int c;
+ int d;
+
+ c = ++b;
+ d = a++;
+ c++;
+ System.out.println("a = " + a);
+ System.out.println("b = " + b);
+ System.out.println("c = " + c);
+ System.out.println("d = " + d);
+ }
+ }


خروجي اين برنامه بقرار زير مي باشد :

a=2
b=3
c=4
d=1



عملگرهاي رفتار بيتي The Bitwise operators
جاوا چندين عملگر رفتار بيتي تعريف نموده كه قابل اعمال روي انواع عدد صحيح
شامل long، int،، short،، char،و byteو مي باشند . اين عملگرها روي بيت هاي
تكي عملوندهاي خود عمل مي كنند . اين عملگرها را در جدول زير خلاصه نموده ايم :
نتيجه آن عملگر
Bitwise unary Not
Not يكاني رفتار بيتي ~ Bitwise AND
AND رفتار بيتي & Bitwise OR
OR رفتار بيتي | Bitwise exclusive OR
OR خارج رفتار بيتي ^ shift right
>> حركت براست shift right zero fill
>>> حركت براست پر شده با صفر shift left
<< حركت به چپ Bitwise AND assignment
انتساب AND رفتار بيتي &= Bitwise OR assignment
انتساب OR رفتار بيتي |= Bitwise exclusive OR assignment
انتساب OR خارج رفتار بيتي ^= shift right assignment
انتساب حركت راست = >>shift right zero fill assignment
انتساب حركت براست پر شده با صفر = >>>shift left assignment
انتساب حركت به چپ = <<
از آنجاييكه عملگرهاي رفتار بيتي با بيت هاي داخل يك عدد صحيح سر و كار
دارند ، بسيار مهم است بدانيم كه اين سر و كار داشتن چه تاثيري ممكن است روي
يك مقدار داشته باشد . بخصوص بسيار سودمند است بدانيم كه جاوا چگونه مقادير
عدد صحيح را ذخيره نموده و چگونه اعداد منفي را معرفي مي كند . بنابراين ، قبل
از ادامه بحث ، بهتر است اين دو موضوع را باختصار بررسي نماييم .
كليه انواع صحيح بوسيله ارقام دودوئي ( باينري ) داراي پهناي بيتي گوناگون
معرفي ميشوند. بعنوان مثال ، مقدار byte عدد 42 در سيستم باينري معادل 00101010
است ، كه هر يك از اين نشانه ها يك توان دو را نشان مي دهند كه با 2 به توان 0
در بيت سمت راست شروع شده است . يا موقعيت بعدي بيت بطرف چپ 2'يا 2ا است و به
طرف چپ بيت بعدي 2 به توان 2يا 4ا است ، بعدي 8 ، 16 ، 32 و همينطور الي آخر
هستند . بنابراين عدد 42 بيت 1 را در موقعيتهاي اول ، سوم و پنجم ( از سمت
راست درنظربگيريد ) دارد. بدين ترتيب 42 معادل جمع 5 بتوان 3+2 بتوان 1+2 بتوان 2
يعني 2+8+32 مي باشد .
كليه انواع عدد صحيح ( باستثنائ char ) اعداد صحيح علامت دار هستند . يعني
كه اين انواع مقادير منفي را همچون مقادير مثبت مي توانند معرفي كنند . جاوا
از يك روش رمزبندي موسوم به مكمل دو (two's complement) استفاده مي كند كه در
آن ارقام منفي با تبديل ( تغيير 1به 0 و بالعكس ) كليه بيت هاي يك مقدار و
سپس اضافه نمودن 1 به آن معرفي مي شوند . بعنوان مثال براي معرفي 42 ، ابتدا
كليه بيت هاي عدد 42 (00101010) را تبديل مي نماييم كه 11010101 حاصل مي شود
آنگاه 1 را به آن اضافه مي كنيم . كه حاصل نهايي يعني 11010110 معرف عدد 42
خواهد بود . براي رمز گشايي يك عدد منفي ، كافي است ابتدا كليه بيت هاي آن را
تبديل نموده ، آنگاه 1 را به آن اضافه نماييم . 42- يعني 11010110 پس از تبديل
برابر 00101001 يا 41 شده و پس از اضافه نمودن 1 به آن برابر 42 خواهد شد .
دليل اينكه جاوا( واكثر زبانهاي برنامه نويسي )از روش مكمل دو(two's complement)
استفاده مي كنند ، مسئله تقاطع صفرها (Zero crossing) است . فرض كنيد يك مقدار byte
براي صفر با 00000000 معرفي شده باشد. در روش مكمل يك (one's complement)
تبديل ساده كليه بيت ها منجر به 11111111 شده كه صفر منفي را توليد مي كند .
اما مشكل اين است كه صفر منفي در رياضيات عدد صحيح غير معتبر است . اين مشكل
بااستفاده از روش مكمل دو (two's complement) براي معرفي مقادير منفي حل خواهد
شد . هنگام استفاده از روش مكمل دو ، 1 به مكمل اضافه شده و عدد 100000000
توليد مي شود . اين روش بيت 1 را در منتهي اليه سمت چپ مقدار byte قرار داده
تا رفتار مورد نظر انجام گيرد، جايي كه 0با 0ا يكسان بوده و 11111111 رمزبندي
شده 1 است . اگر چه در اين مثال از يك مقدار byte استفاده كرديم ، اما همين
اصول براي كليه انواع عدد صحيح جاوا صدق مي كنند .
از آنجاييكه جاوا از روش مكمل دو براي ذخيره سازي ارقام منفي استفاده ميكند
و چون كليه اعداد صحيح در جاوا مقادير علامت دار هستند بكار بردن عملگرهاي
رفتار بيتي براحتي نتايج غير منتظره اي توليد مي كند . بعنوان مثال برگرداندن
بيت بالاتر از حد مجاز (high-order) سبب مي شود تا مقدار حاصله بعنوان يك رقم
منفي تفسير شود ، خواه چنين قصدي داشته باشيد يا نداشته باشيد . براي جلوگيري
از موارد ناخواسته ، فقط بياد آوريد كه بيت بالاتر از حد مجاز (high-order)
علامت يك عدد صحيح را تعيين مي كند، صرفنظر از اينكه بيت فوق چگونه مقدار گرفته
باشد .

عملگرهاي منطقي رفتار بيتي
عملگرهاي منطقي رفتار بيتي شامل &، |،، ^،، ~، هستند. جدول زير حاصل هر يك
از اين عمليات را نشان مي دهد . در بحث بعدي بياد داشته باشيد كه عملگرهاي
رفتار بيتي به بيت هاي منفرد داخل هر عملوند اعمال مي شوند .

A B A|B A&B A^B ~A
0 0 0 0 0 1
1 0 1 0 1 0
0 1 1 0 1 1
1 1 1 1 0 0

NOT

رفتار بيتي
عملگر NOT يكاني يعني ~ كه آن را مكمل رفتار بيتي (bitwise complement) هم
مي نامند ، كليه بيت هاي عملوند خود را تبديل مي كند . بعنوان مثال ، عدد 42
كه مطابق الگوي بيتي زير است : 00101010

پس از اعمال عملگر NOT بصورت زير تبديل مي شود : 11010101

AND
رفتار بيتي
عملگر AND يعني & اگر هر دو عملوند 1 باشند ، يك بيت 1 توليد مي كند . در
كليه شرايط ديگر يك صفر توليد مي شود . مثال زير را نگاه كنيد : 00101010 42
& 00001111 15

00001010 10

OR
رفتار بيتي
عملگر OR يعني | بيت ها را بگونه اي تركيب مي كند كه اگر هر يك از بيت هاي
عملوندها 1 باشد ، آنگاه بيت حاصله نيز 1 خواهد بود . به مثال زير نگاه كنيد : 00102010 42
| 00001111 15

00101111 47

XOR
رفتار بيتي
عملگر XOR يعني ^ بيت ها را بگونه اي تركيب مي كند كه اگر دقيقا" يك عملوند 1
باشد ، حاصل برابر 1 خواهد شد . در غير اينصورت ، حاصل 0 مي شود .
مثال بعدي چگونگي كار اين عملگر را نشان مي دهد . اين مثال همچنين يكي از
خصلتهاي سودمند عملگر XOR را نمايش مي دهد . دقت كنيد كه هر جا عملوند دوم يك
بيت 1 داشته باشد ، چگونه الگوي بيتي عدد 42 تبديل مي شود . هر جا كه عملوند
دوم بيت 0 داشته باشد ، عملوند اول بدون تغيير مي ماند . هنگام انجام برخي از
انواع عملكردهاي بيتي ، اين خصلت بسيار سودمند است . 00101010 42
^ 00001111 15

00100101 37


استفاده از عملگرهاي منطقي رفتار بيتي
برنامه بعدي نشان دهنده عملگرهاي منطقي رفتار بيتي است :

+ // Demonstrate the bitwise logical operators.
+ class BitLogic {
+ public static void main(String args[] ){
+ String binary[] = {
+ "0000"/ "0001"/ "0010"/ "0011"/ "0100"/ "0101"/ "0110"/ "0111"/
+ "1000"/ "1001"/ "1010"/ "1011"/ "1100"/ "1101"/ "1110"/ "1111"
+ };
+ int a = 3; // 0 + 2 + 1 or 0011 in binary
+ int b = 6; // 4 + 2 + 0 or 0110 in binary
+ int c = a | b;
+ int d = a & b;
+ int e = a ^ b;
+ int f =( ~a & b )|( a & ~b);
+ int g = ~a & 0x0f;
+
+ System.out.println(" a = " + binary[a]);
+ System.out.println(" b = " + binary[b]);
+ System.out.println(" a|b = " + binary[c]);
+ System.out.println(" a&b = " + binary[d]);
+ System.out.println(" a^b = " + binary[e]);
+ System.out.println("~a&b|a&~b = " + binary[f]);
+ System.out.println(" ~a = " + binary[g]);
+ }
+ }


در اين مثال ، aو bو الگوهاي بيتي دارند كه كليه چهار احتمال براي ارقام
دو تايي باينري را معرفي مي كنند . 0-0، 0-1،، 1-0،و 1-1و . مي توانيد مشاهده
كنيد چگونه |و &و روي هر يك از بيت ها با توجه به نتايج در cو dو عمل مي كنند.
مقادير نسبت داده شده به eو fو مشابه بوده و نشان دهنده چگونگي كار عملگر ^
مي باشند . آرايه رشته اي با نام binary معرفي ارقام 0 تا 15 را بصورت باينري و
قابل خواندن براي انسان نگهداري مي كند . در اين مثال ، آرايه فوق طوري نمايه
سازي شده تا معرفي باينري هر يك از نتايج را نشان دهد . آرايه طوري ساخته شده
كه معرفي رشته اي صحيح يك مقدار باينري n را در binary[n] ذخيره مي كند . مقدار ~a
بوسيله عملگر ANDبا oxofا( 00001111 باينري ) عمل شده تا مقدار آن را به
كمتر از 16 كاهش دهد تا بتوان با استفاده از آرايه binary از آن چاپ گرفت .
اكنون خروجي اين برنامه بصورت زير مي باشد :

a=1011
b=0110
a^Eb=0111
a&b=0010
a&b=0101
~a&b^Ea&~b=0101
~a=1100



حركت به چپ
كليه بيت هاي موجود در يك مقدار را به تعداد <<عملگر حركت به چپ يعني
دفعات مشخص بطرف چپ منتقل مي كند . شكل كلي آن بقرار زير است :

Value << num


تعداد دفعات مقدار
در ايجا num مشخص كننده تعداد مكانهايي است كه بيت هاي موجود در value بايد
كليه بيت هاي موجود در يك مقدار مشخص را <<به چپ انتقال يابند . بدين ترتيب
بتعداد مكانهايي كه در num مشخص شده بطرف چپ حركت مي دهد . براي هر بار حركت
به چپ ، بيت high-order ( بيش از حد مجاز ) منتقل شده و از دست خواهد رفت و
يك صفر در طرف راست مقدار ، جايگزين مي شود . بدين ترتيب هنگاميكه يك حركت به
چپ روي يك عملوند int عمل مي كند ، بيت هاي گذشته از مكان 31 از دست خواهند
رفت . اگر عملوند يك long باشد، بيت ها پس از گذشتن از مكان 63 از دست ميروند.
هنگاميكه مقادير byteو shortو را انتقال مي دهيد ، ارتقائ خودكار انواع در
جاوا نتايج غير منتظره اي ايجاد مي كند . حتما" مي دانيد كه هنگام ارزشيابي
عبارات ، مقادير byteو shortوبه int ارتقائ مي يابند. بعلاوه جواب چنين عبارتي
از نوع int خواهد بود . بنابراين حاصل يك حركت به چپ روي مقادير byteو shortو
يك int خواهد بود و بيت هاي انتقال يافته به چپ تا زمانيكه از مكان بيت 31
نگذرند ، از دست نمي روند . علاوه براين ، يك مقدار منفي byteو shortو هنگاميكه
به int ارتقائ مي يابد ، بسط علامت پيدا مي كند . بنابراين بيت هاي بيش از حد
مجاز با بيت 1 پر مي شوند . بخاطر اين دلايل ، انجام يك حركت به چپ روي byte و short
مستلزم آن است كه از بايت هاي بيش از حد مجاز در جواب int دست بكشيد .
بعنوان مثال ، اگر يك مقدار byte را حركت به چپ بدهيد ، آن مقدار ابتدا به نوع int
تبديل شده و سپس انتقال خواهد يافت . بايد سه بايت بالايي حاصل را از دست
بدهيد . اگر بخواهيد حاصل يك مقدار byte انتقال يافته را بدست آوريد . بايد سه
بايت بالايي حاصل را از دست بدهيد . آسان ترين روش براي انجام اينكار استفاده
از تبديل cast و تبديل جواب به نوع byte است . مثال بعدي همين مفهوم را براي
شما آشكار مي سازد :

+ // Left shifting a byte value.
+ class ByteShift {
+ public static void main(String args[] ){
+ byte a = 64/ b;
+ int i;
+
+ i = a << 2;
+ b =( byte( )a << 2);
+
+ System.out.println("Original value of a :" + a);
+ System.out.println("i and b :" + i + " " + b);
+ }
+ }


خروجي توليد شده توسط اين برنامه بقرار زير مي باشد :

original value of a:64
i and b :256 0


چون براي اهداف ارزشيابي ، a به نوع int ارتقائ يافته ، دوبار حركت به چپ
مقدار 64 (0000 َ0100) منجر به i مي گردد كه شامل مقدار 256 (0000 َ1 0000)
مي باشد . اما مقدار b دربرگيرنده صفر است زيرا پس از انتقال ، بايت كمتر از
حد مجاز (loworder) اكنون شامل صفر است . تنها بيت دربرگيرنده 1 به بيرون
انتقال يافته است .
از آنجاييكه هر بار حركت به چپ تاثير دو برابر سازي مقدار اصلي را دارد
برنامه نويسان اغلب از اين خاصيت بجاي دو برابر كردن استفاده مي كنند . اما
بايد مراقب باشيد . اگر يك بيت 1 را به مكان بيت بيش از حد مجاز (31 يا 63)
منتقل كنيد ، مقدار فوق منفي خواهد شد . برنامه بعدي همين نكته را نشان ميدهد.

+ // Left shifting as a quick way to multiply by 2.
+ class MultByTwo {
+ public static void main(String args[] ){
+ int i;
+ int num = 0xFFFFFFE;
+
+ for(i=0; i<4; i++ ){
+ num = num << 1;
+ System.out.println(num);
+ }
+ }
+ }


خروجي اين برنامه بقرار زير خواهد بود : 536870908


1073741816
2147483632
- 32


مقدار آغازين را با دقت انتخاب كرده ايم بطوريكه بيت بعد از چهار مكان حركت
بطرف چپ ، مقدار 32- را توليد نمايد . همانطوريكه مي بينيد ، هنگاميكه بيت 1
به بيت 31 منتقل مي شود ، رقم بعنوان منفي تفسير خواهد شد .

حركت به راست
كليه بيت هاي موجود در يك مقدار را به تعداد >>عملگر حركت به راست يعني
دفعات مشخص بطرف راست انتقال مي دهد . شكل كلي آن بقرار زير مي باشد :

value >> num


تعداد دفعات مقدار
در اينجا ، num مشخص كننده تعداد مكانهايي است كه بيت هاي value بايد بطرف
كليه بيت هاي يك مقدار مشخص شده را به تعداد >>راست انتقال يابند . يعني
مكانهاي بيتي مشخص شده توسط num بطرف راست انتقال مي دهد .
كد قطعه اي زير مقدار 32 را دو مكان بطرف راست منتقل مي كند و آنگاه جواب
آن در a معادل 8 قرار مي گيرد :

+ int a = 32;
+ a = a >> 2; // a now contains 8


اگر بيت هايي از يك مقدار به بيرون منتقل شوند ، آن بيت ها از دست خواهند
رفت . بعنوان مثال كد قطعه اي بعدي مقدار 35 را دو مكان بطرف راست منتقل نموده
و باعث مي شود تا دو بيت كمتر از حد مجاز از دست رفته و مجددا" جواب آن در a
معادل 8 قرار گيرد .

+ int a = 35;
+ a = a >> 2; // a still contains 8


همين عمليات را در شكل باينري نگاه مي كنيم تا اتفاقي كه مي افتد ، روشن تر
شود : 00100011 35
>> 2
00001000 8

هر بار كه يك مقدار را به طرف راست منتقل مي كنيد ، آن مقدار تقسيم بر دو
مي شود و باقيمانده آن از دست خواهد رفت . مي توانيد از مزاياي اين روش در
تقسيم بر دو اعداد صحيح با عملكرد سطح بالا استفاده نماييد . البته ، بايد مطمئن
شويد كه بيت هاي انتهايي سمت راست را به بيرون منتقل نكنيد .
هنگاميكه حركت بطرف راست را انجام مي دهيد ، بيت هاي بالايي ( از سمت چپ )
در معرض حركت بطرف راست قرار گرفته ، با محتوي قبلي بيت بالايي پر مي شوند .
اين حالت را بسط علامت (sign extension) ناميده و براي محفوظ نگهداشتن علامت
ارقام منفي هنگام حركت بطرف راست استفاده مي شوند. بعنوان مثال 1>>8- معادل 4-
است كه به شكل باينري زير مي باشد : 11111000- 8
>> 1
11111100- 4

جالب است بدانيد كه اگر 1- را بطرف راست حركت دهيد، حاصل آن همواره 1- باقي
مي ماند ، چون بسط علامت ، مراقب آوردن يك بيت ديگر در بيت هاي بيش از حد مجاز
خواهد بود .
گاهي هنگام حركت بطرف راست مقادير ، مايل نيستيم تا بسط علامت اجرا شود .
بعنوان مثال ، برنامه بعدي يك مقدار نوع byte را به معرفي رشته اي در مبناي 16
تبديل مي كند . دقت كنيد كه مقدار منتقل شده با استفاده از عملگر ANDيا oxofا
پوشانده شده تا هر گونه بيت هاي بسط يافته علامت را بدور اندازد بطوريكه مقدار
فوق را بتوان بعنوان يك نمايه به آرايه اي از كاراكترهاي در مبناي 16 استفاده
نمود .

+ // Masking sign extension.
+ class HexByte {
+ static public void main(String args[] ){
+ char hex[] = {
+ '0'/ '1'/ '2'/ '3'/ '4'/ '5'/ '6'/ '7'/
+ '8'/ '9'/ 'a'/ 'b'/ 'c'/ 'd'/ 'e'/ 'f'
+ };
+ byte b =( byte )oxf1
+
+ System.out.println("b = ox" + hex[(b >> 4 )& oxof] + hex[b & oxof]);
+ }
+ }


خروجي اين برنامه بقرار زير مي باشد :

b=oxf1



حركت به راست فاقد علامت
بطور خودكار >>اكنون مي دانيد كه هر بار يك انتقال اتفاق مي افتد ، عملگر
جاي خالي بيت بيش از حد مجاز را با محتوي قبلي اش پر مي كند . اين عمل سبب حفظ
علامت آن مقدار مي گردد . اما گاهي تمايلي براي اينكار نداريم . بعنوان مثال
مي خواهيد چيزي را منتقل كنيد كه معرف يك مقدار عددي نيست . بالطبع نمي خواهيد
عمل بسط علامت انجام گيرد . اين حالت هنگام كار با مقادير براساس پيكسل (pixel)
و گرافيك اغلب وجود دارد . در چنين شرايطي لازم است تا مقدار صفر در بيت بيش از
حد مجاز قرار گيرد ، صرفنظر از اينكه مقدار قبلي در آن بيت چه بوده است . اين
حالت را انتقال فاقد علامت (usigned shift) مي گويند. براي اين منظور، از عملگر
استفاده كنيد كه صفرها را در بيت بيش >>>حركت به راست فاقد علامت در جاوا يعني
از حد مجاز منتقل مي كند .
مي باشد . در اينجا >>>كد قطعه اي زير نشان دهنده عملگر a معادل 1- است كه
كليه 32 بيت را در باينري روي 1 تنظيم مي كند . اين مقدار سپس 24 بيت بطرف
راست انتقال مي يابد، و 24 بيت بالايي را با صفرها پر مي كند و بسط علامت معمولي
را ناديده مي گيرد . بدين ترتيب a معادل 255 مي باشد . + int a =- 1;
+ a = a >>> 24;

اينجا همان عمليات را در شكل باينري مشاهده مي كنيد تا بهتر بفهميد چه
اتفاقي افتاده است : 1
در باينري بعنوان يك int 11111111 11111111 11111111 11111111 >>>24
255
در باينري بعنوان يك int َ11111111 00000000 00000000 00000000
اغلب اوقات آنچنان سودمند كه بنظر مي رسد ، نبوده چون فقط براي >>>عملگر
مقادير 32 بيتي و 64 بيتي معني دارد . بياد آوريد كه مقادير كوچكتر در عبارات
بطور خودكار به int ارتقائ مي يابند . بدين ترتيب بسط علامت اتفاق افتاده و
حركت بجاي مقادير 8 بيتي و 16 بيتي روي مقادير 32 بيتي انجام مي شود . يعني
بايد انتظار يك حركت به راست فاقد علامت روي يك مقدار byte داشته باشيم كه در
بيت 7 ، صفر را قرار مي دهد . اما واقعا" اينطور نيست ، چون در واقع مقدار 32
بيتي است كه منتقل مي شود . برنامه بعدي اين تاثيري را نشان مي دهد .

+ // Unsigned shifting a byte value.
+ class ByteUShift {
+ static public void main(String args[] ){
+ char hex[] = {
+ '0'/ '1'/ '2'/ '3'/ '4'/ '5'/ '6'/ '7'/
+ '8'/ '9'/ 'a'/ 'b'/ 'c'/ 'd'/ 'e'/ 'f'
+ };
+ byte b =( byte )oxf1
+ byte c =( byte( )b >> 4);
+ byte d =( byte( )b >>> 4);
+ byte e =( byte(( )b & oxff )>> 4);
+
+ System.out.println(" b = ox"
+ + hex[(b >> 4 )& oxof] + hex[b & oxof]);
+ System.out.println(" b >> 4 = ox"
+ + hex[(c >> 4 )& oxof] + hex[c & oxof]);
+ System.out.println(" b >>> 4 = ox"
+ + hex[(d >> 4 )& oxof] + hex[d & oxof]);
+ System.out.println("(b & oxof )>> 4 = ox"
+ + hex[(e >> 4 )& oxof] + hex[e & oxof]);
+ }
+ }


چگونه هنگام كار با بايت ها عملي >>>خروجي اين برنامه نشان ميدهد كه عملگر
انجام نمي دهد . متغير b بعنوان يك مقدار byte منفي قراردادي در اين نمايش
تنظيم شده است . سپس مقدار byteدر bر كه چهار مكان بطرف راست انتقال بافته به C
منتسب مي شود كه بخاطر بسط علامت مورد انتظار oxff است . سپس مقدار byteدر bر
كه چهار مكان بطرف راست و فاقد علامت منتقل شده به d منتسب مي شود كه انتظار
داريد oxof باشد ، اما در حقيقت oxff است چون بسط علامت هنگاميكه b به نوع int
قبل از انتقال ارتقائ يافته اتفاق افتاده است . آخرين عبارت ، e را در مقدار byte
متغير b كه با استفاده از عملگر ANDبا 8ا بيت پوشانده شده تنظيم نموده و
سپس چهار مكان بطرف راست منتقل مي كند كه مقدار مورد انتظار oxof را توليد
مي كند . دقت كنيد كه عملگر حركت به راست فاقد علامت براي d استفاده نشد ، چون
حالت بيت علامت بعد از AND شناخته شده است .

b=oxf1
b>>4=oxff
b>>>4=oxff
( b&oxff)>>4=oxof



انتسابهاي عملگر رفتار بيتي
كليه عملگرهاي رفتار بيتي باينري يك شكل مختصر مشابه باعملگرهاي جبري دارند
كه عمل انتساب را با عمليات رفتار بيتي تركيب مي كنند. بعنوان مثال ، دو دستور
بعدي كه مقدار a را چهار بيت به راست حركت مي دهند ، معادل يكديگرند :

+ a = a >> 4;
+ a >>= 4;


بطور مشابه ، دو دستور زير كه a را به عبارت روش بيتي aoRb منتسب مي كنند
معادل يكديگرند :

+ a = a | b;
+ a |= b;


برنامه بعدي تعدادي از متغيرهاي عدد صحيح را بوجود آورده آنگاه از شكل
مختصر انتسابهاي عملگر رفتار بيتي براي كار كردن بااين متغيرها استفاده ميكند:

+ class OpBitEquals {
+ public static void main(String args[] ){
+ int a = 1;
+ int b = 2;

Nesta
01-07-2005, 07:23
عملگرهاي رابطه اي

اين عملگرها تعيين كننده رابطه ها بين يك عملوند با عملوند ديگر هستند. بطور
مشخص ، آنها تساوي يا ترتيب بندي (ordering) را معين ميكنند. عملگرهاي رابطه اي
را در زير نشان داده ايم :
نتيجه آن عملگر

مساوي با ==
نامساوي با !=
>بزرگتر از
<كوچكتر از
بزرگتر از يا مساوي با = >
كوچكتر از يا مساوي با = <

حاصل اين عمليات يك مقدار boolean است . از عملگرهاي رابطه اي بخصوص در
عباراتي كه دستور if و انواع دستورات حلقه اي را كنترل مي كنند ، زياد استفاده
مي شوند .
هر نوعي در جاوا شامل اعداد صحيح ، ارقام اعشاري ، كاراكترها و عبارات بولي
را مي توان بوسيله آزمون تساوي == و آزمون عدم تساوي != مقايسه نمود . دقت
نماييد كه در جاوا ( نظير Cو C++و ) تساوي توسط دو علامت تساوي و نه يك علامت
نشان داده مي شود . ( بياد آوريد كه علامت تكي تساوي يك عملگر انتساب است . )
عملگرهاي ترتيب بندي فقط براي مقايسه انواع عددي بكار مي روند . يعني فقط
عملوندهاي اعداد صحيح ، اعداد اعشاري و كاراكترها را مي توان مقايسه نمود و
و تعيين كرد كه كداميك از ديگري بزرگتر يا كوچكتر است .
گفتيم كه نتيجه توليد شده توسط يك عملگر رابطه اي ، يك مقدار boolean است .
بعنوان مثال ، كد قطعه اي زير كاملا" معتبر است :

+ int a = 4;
+ int b = 1;
+ boolean c = a < b;


در اين حالت ، جواب b اگر سابق برنامه نويسي C++/C داريد ، به نكته زير توجه نماييد . در C++/C
اين نوع از دستورات بسيار رايج است .

+ int done;
+ //...
+ if(!done ... )// Valid in C/C++
+ if(done ... )// but not in Java.


در جاوا ، آن دستورات بايد بصورت زير دوباره نويسي شوند :

+ if(done == 0 ... )// This is Java-style.
+ if(done != 0... )


علت آن است كه در جاوا صحيح و ناصحيح (true and false) مشابه C++/C تعريف
نشده است . در C++/C صحيح هر مقدار غير صفر و ناصحيح معادل صفر است . در جاوا true
و falseو مقادير غيرعادي هستند كه ربطي با صفر يا غيرصفر ندارند. بنابراين
براي آزمون صفر و غير صفر، بايد بطور صريح يك يا چند عملگر رابطه اي را استخدام

Nesta
01-07-2005, 07:24
عملگرهاي منطقي بولي Boolean

عملگرهاي منطقي بولي كه در زير نشان داده ايم فقط روي عملوندهاي بولي عمل
مي كنند . كليه عملگرهاي منطقي باينري دو مقدار boolean را تركيب مي كنند تا
يك مقدار منتج boolean ايجاد نمايند .
نتيجه آن عملگر
AND
منطقي & OR
منطقي | XOR
منطقي ( خارج ) ^ OR
مدار كوتاه || AND
مدار كوتاه && NOT
يكاني منطقي !
انتساب AND &=
انتساب OR |=
انتساب XOR ^=
مساوي با ==
نامساوي با !=
سه تايي if-tethen-eselse :?
عملگرهاي بولي منطقي &، |،، ^، روي مقادير Boolean همانطوري كه روي بيت هاي
يك عدد صحيح رفتار مي كنند ، عمل خواهند كرد . عملگر منطقي ! حالت بولي را
معكوس مي كند :

!false=true t!true=false

جدول بعدي تاثيرات هر يك از عمليات منطقي را نشان مي دهد :

A B A|B A&B A^B !A
False False False False False True
True False True False True False
False True True False True True
True True True True False False



در زير برنامه اي را مشاهده مي كنيد كه تقريبا" با مثال Bitlogic قبلي برابر
است ، اما در اينجا بجاي بيت هاي باينري روي مقادير منطقي بولي عمل مي كند :

+ // Demonstrate the boolean logical operators.
+ class BoolLogic {
+ public static void main(String args[] ){
+ boolean a = true;
+ boolean b = false;
+ boolean c = a | b;
+ boolean d = a & b;
+ boolean e = a ^ b;
+ boolean f =( !a & b )|( a & !b);
+ boolean g = !a;
+ System.out.println(" a = " + a);
+ System.out.println(" b = " + b);
+ System.out.println(" a|b = " + c);
+ System.out.println(" a&b = " + d);
+ System.out.println(" a^b = " + e);
+ System.out.println("!a&b|a&!b = " + f);
+ System.out.println(" !a = " + g);
+ }
+ }


پس از اجراي اين برنامه ، شما همان قوانين منطقي كه براي بيت ها صادق بود
در مورد مقادير boolean مشاهده مي كنيد . در خروجي اين برنامه مشاهده مي كنيد
كه معرفي رشته اي يك مقدار بولي درجاوا يكي از مقادير لفظي trueيا falseا است .

a = true
b = false
a|b = true
a&b = false
a^b = true
!a&b|a&!b = true
!a = false



عملگرهاي منطقي مدار كوتاه
جاوا دو عملگر بولي بسيار جالب دارد كه در اكثر زبانهاي ديگر برنامه نويسي
وجود ندارند . اين ها روايت ثانويه عملگرهاي ANDو ORو بولي هستند و بعنوان
عملگرهاي منطقي مدار كوتاه معرفي شده اند. در جدول قبلي مي بينيد كه عملگر OR
هرگاه كه A معادل true باشد، منجر به true مي شود، صرفنظر از اينكه B چه باشد.
بطور مشابه ، عملگر AND هرگاه A معادل false باشد منجر به false مي شود. صرفنظر
از اينكه B چه باشد . اگر از اشكال ||و &&و بجاي |و &و استفاده كنيد، هنگاميكه
حاصل يك عبارت مي تواند توسط عملوند چپ بتنهايي تعيين شود ، جاوا ديگر به
ارزيابي عملوند راست نخواهد پرداخت . اين حالت بسيار سودمند است بخصوص وقتي كه
عملوند سمت راست بستگي به عملوند سمت چپ و trueيا falseا بودن آن براي درست
عمل كردن داشته باشد . بعنوان مثال ، كد قطعه اي زير به شما نشان مي دهد چگونه
مي توانيد مزاياي ارزيابي منطقي مدار كوتاه را استفاده نموده تا مطمئن شويد
كه عمليات تقسيم قبل از ارزيابي آن معتبر است .

+ if(denom != 0 && num / denom > 10)


از آنجاييكه شكل مدار كوتاه AND يعني && استفاده شده است ، هنگاميكه denom
صفر باشد ، خطر ايجاد يك استثنائ حين اجرا منتفي است . اگر همين خط از كد را
با استفاده از رايت تكي AND يعني & بنويسيم ، هر دو عملوند بايد مورد ارزيابي
قرار گيرند و هنگاميكه denom صفر باشد يك استثنائ حين اجرا بوجود مي آيد .
در حالتهايي كه شامل منطق بولي باشند : استفاده از ارزيابيهاي مدار كوتاه AND
و ORو يك روش استاندارد است كه روايتهاي تك كاراكتري عملگرها را منحصرا"
براي عمليات رفتار بيتي قرار مي دهد . اما استثنائاتي بر اين قوانين وجود
دارند . بعنوان مثال ، دستور زير را در نظر بگيريد :

+ if(c==1 & e++ < 100 )d = 100;


در اينجا استفاده از يك علامت & تكي اطمينان مي دهد كه عمليات افزايشي به e

Nesta
01-07-2005, 07:25
عملگر انتساب The Assignment Operator

عملگر انتساب علامت تكي تساوي = مي باشد . عملگر انتساب در جاوا مشابه ساير
زبانهاي برنامه نويسي كار مي كند . شكل كلي آن بصورت زير است :

Var = expression;


عبارت متغير
در اينجا نوع var ( متغير ) بايد با نوع experssion ( عبارت ) سازگار باشد.
عملگر انتساب يك خصلت جالب دارد كه ممكن است با آن آشنايي نداشته باشيد :
به شما امكان مي دهد تا زنجيره اي از انتسابها بوجود آوريد . بعنوان مثال ، اين
قطعه از يك برنامه را در نظر بگيريد :

+ int x/ y/ z;
+
+ x = y = z = 100; // set x/ y/ and z to 100


اين قطعه از برنامه مقدار 100 را با استفاده از يك دستور در متغيرهاي x، y،
و z قرار مي دهد . زيرا = عملگري است كه مقدار عبارت سمت راست را جذب مي كند .
بنابراين مقدار Z=100 برابر 100 است كه اين مقدار به y منتسب شده و نيز به x
منتسب خواهد شد . استفاده از " زنجيره اي از انتسابها " يك راه آسان براي قرار ادن يك مقدار مشترك در گروهي از متغيرهاست .

Nesta
01-07-2005, 07:25
عملگر ?

جاوا شامل يك عملگر سه تايي ويژه است كه مي تواند جايگزين انواع مشخصي از
دستورات if-then-else باشد. اين عملگر علامت ? است و نحوه كار آن در جاوا مشابه
با Cو C++و است . ابتدا كمي گيج كننده است ، اما مي توان از ? براحتي و با
كارايي استفاده نمود شكل كلي اين عملگر بصورت زير است :

experssion 1? experssion2 :experssion3


در اينجا experssion1 مي تواند هر عبارتي باشد كه با يك مقدار بولي سنجيده
مي شود . اگر experssion1 صحيح true باشد ، آنگاه experssion2 سنجيده مي شود
در غير اينصورت experssion3 ارزيابي خواهد شد . نتيجه عمليات ? همان عبارت
ارزيابي شده است . هر دو عبارت experssion2و experssion3و بايد از يك نوع باشند
كه البته void نمي تواند باشد .
در اينجا مثالي براي استفاده از عملگر ? مشاهده مي كنيد :

+ ratio = denom == 0 ? 0 : num / denom;


هنگاميكه جاوا اين عبارت انتساب را ارزيابي مي كند ، ابتدا به عبارتي كه
سمت چپ علامت سئوال قرار دارد ، نگاه مي كند. اگر denom مساوي صفر باشد ، آنگاه
عبارت بين علامت سئوال و علامت (colon) ارزيابي شده و بعنوان مقدار كل عبارت ?
استفاده مي شود . اگر denom مساوي صفر نباشد ، آنگاه عبارت بعد از (colon)
ارزيابي شده و براي مقدار كل عبارت ? استفاده مي شود . نتيجه توليد شده توسط
عملگر ? سپس به ratio نسبت داده مي شود .
در زير برنامه اي مشاهده مي كنيد كه عملگر ? را نشان مي دهد . اين برنامه از
عملگر فوق براي نگهداري مقدار مطلق يك متغير استفاده مي كند .

+ // Demonstrate ?.
+ class Ternary {
+ public static void main(String args[] ){
+ int i/ k;
+
+ i = 10;
+ k = i < 0 ?- i : i; // get absolute value of i
+ System.out.print("Absolute value of ");
+ System.out.println(i + " is " + k);
+ }
+ }


خروجي اين برنامه بصورت زير مي باشد :

Absolute value of 10 is 10
Absolute value of- 10 is 10



حق تقدم عملگر
جدول زير ترتيب حق تقدم عملگرهاي جاوا را از بالاترين اولويت تا پايين ترين
نشان مي دهد . دقت كنيد كه در سطر اول اقلامي وجود دارد كه معمولا" بعنوان عملگر
درباره آنها فكر نمي كنيد : پرانتزها ، كروشه ها و عملگر نقطه .

Highest
)( [].
++ -- ~ !
* / %
+-
>> >>> <<
> >= < <=
== !=
&
^
|
&&
||
?:
= op=
Lowest


از پرانتزها براي تغيير حق تقدم يك عمليات استفاده مي شود . قبلا" خوانده ايد
كه كروشه هاي دوتايي نمايه سازي آرايه ها را فراهم مي سازند . عملگرهاي نقطه يائاستفاده شده كه بعدا" مورد بررسي قرار خواهيم داد.

Nesta
01-07-2005, 07:26
استفاده از پرانتزها

پرانتزها حق تقدم عملياتي را كه دربرگرفته اند ، افزايش مي دهند . اينكار
اغلب براي نگهداري نتيجه دلخواهتان ضروري است . بعنوان مثال ، عبارت زير را در
نظر بگيريد :

+ a >> b + 3


اين عبارت ابتدا 3 را به b اضافه نموده و سپس a را مطابق آن نتيجه بطرف
راست حركت مي دهد. اين عبارت را مي توان با استفاده از پرانتزهاي اضافي بصورت
زير دوباره نويسي نمود :

+ a >>( b + 3)


اما ، اگر بخواهيد ابتدا a را با مكانهاي b بطرف راست حركت داده و سپس 3 را
به نتيجه آن اضافه كنيد ، بايد عبارت را بصورت زير در پرانتز قرار دهيد : +( a >> b )+ 3

علاوه بر تغيير حق تقدم عادي يك عملگر ، پرانتزها را مي توان گاهي براي روشن
نمودن مفهوم يك عبارت نيز بكار برد . براي هر كسي كه كد شما را مي خواند، درك
يك عبارت پيچيده بسيار مشكل است . اضافه نمودن پرانتزهاي اضافي و روشنگر به
عبارات پيچيده مي تواند از ابهامات بعدي جلوگيري نمايد. بعنوان مثال ، كداميك
از عبارات زير راحت تر خوانده و درك مي شوند ?

+ a | 4 + c >> b & 7 || b > a % 3
+( a |((( 4 + c )>> b )& 7 ))||( b >( a % 3))


يك نكته ديگر : پرانتزها ( بطور كلي خواه اضافي باشند يا نه ) سطح عملكرد
برنامه شما را كاهش نمي دهند. بنابراين ، اضافه كردن پرانتزها براي كاهش ابهام نفي روي برنامه شما نخواهد داشت .

Nesta
01-07-2005, 07:27
دستورات كنترلي

زبانهاي برنامه نويسي از دستورات كنترلي استفاده مي كنند تا جريان اجراي
برنامه را پيشرفت داده و براساس تغييرات حالت يك برنامه شاخه هايي از آن برنامه
منشعب نمايند . دستورات كنترلي برنامه در جاوا را مي توان در طبقه بندي بعدي
گنجاند : انتخاب (selection) ، تكرار (iteration) ، و پرش (jump) . دستورات
انتخاب به برنامه شما امكان ميدهند تا مسيرهاي متفاوت اجراي برنامه را براساس
حاصل يك عبارت يا حالت خاص يك متغير انتخاب نماييد . دستورات تكرار اجراي
برنامه را قادر مي سازد تا يك يا چند عبارت را تكرار نمايد ( يعني دستورات
تكرار حلقه ها را تشكيل مي دهند ). دستورات پرش به برنامه شما امكان مي دهند تا
يك روش اجراي غير خطي داشته باشيد . كليه دستورات كنترلي جاوا را در اينجا
بررسي نموده ايم .
نكته : اگر C++/C را ميدانيد، دستورات كنترلي جاوا براي شما بسيار آشنا هستند.
در حقيقت ، دستورات كنترلي جاوا براي برنامه نويسان C++/C بسيار يكسان
است . اما تفاوتهاي محدودي وجود دارد بخصوص در دستورات break و

Nesta
01-07-2005, 07:28
دستورات انتخاب در جاوا

جاوا از دو دستور انتخاب پشتيباني مي كنند : ifو switchو . با اين دستورات
شما اجراي برنامه را براساس شرايطي كه فقط حين اجراي برنامه اتفاق مي افتند
كنترل مي كنيد. اگر سابقه برنامه نويسي با C++/C را نداريد، از قدرت و انعطاف
پذيري موجود در اين دو دستور متعجب و شگفت زده خواهيد شد .


if


دستور if دستور انشعاب شرطي در جاوا است . از اين دستور مي توان استفاده
نمود و اجراي برنامه را طي دو مسير متفاوت به جريان انداخت . شكل كلي اين دستور
بصورت زير است :

if( condition )statement 1;
else statement 2;


دراينجا هر statement ممكن است يك دستور منفرد يا يك دستور مركب قرار گرفته
در ابروها ( يعني يك بلوك ) باشد . condition ( شرط ) هر عبارتي است كه يك
مقدار boolean را برمي گرداند . جمله else اختياري است . if
بصورت زير كار مي كند : اگر شرايط محقق باشد ، آنگاه statement 1 اجرا
مي شود . در غير اينصورت statement 2 ( در صورت وجود ) اجرا خواهد شد .
تحت هيچ شرايطي هر دو دستور با هم اجرا نخواهند شد . بعنوان مثال ، در نظر
بگيريد :

+ int a/ b;
+ //...
+ if(a < b )a = 0;
+ else b = 0;


در اينجا اگر a كوچكتر از b باشد ، آنگاه a برابر صفر مي شود . در غير
اينصورت b برابر صفر قرار مي گيرد . در هيچ شرايطي اين دو متغير در آن واحد
برابر صفر نمي شوند .
غالب اوقات ، عبارتي كه براي كنترل if استفاده ميشود شامل عملگرهاي رابطه اي
است . اما از نظر تكنيكي ضرورتي وجود ندارد . مي توان با استفاده از يك متغير boolean
تكي ، if را همانطوريكه در بخش زير مشاهده مي كنيد ، كنترل نمود .

+ boolean dataAvailable;
+ //...
+ if( dataAvailable)
+ ProcessData)(;
+ else
+ waitForMoreData)(;


بياد آوريد كه فقط يك دستور مي تواند مستقيما" بعداز ifيا elseا قرار گيرد.
اگر بخواهيد دستورات بيشتري داخل نماييد ، نيازي به ايجاد يك بلوك نداريد
نظير اين قطعه كه در زير آمده است :

+ int bytesAvailable;
+ //...
+ if( bytesAvailable > 0 ){
+ ProcessData)(;
+ bytesAvailable- = n;
+ } else
+ waitForMoreData)(;


در اينجا ، هر دو دستور داخل بلوك if اجرا خواهند شد اگر bytes Available
بزرگتر از صفر باشد .
برخي از برنامه نويسان راحت ترند تا هنگام استفاده از if ، از ابروهاي باز
و بسته استفاده نمايند، حتي زمانيكه فقط يك دستور در هر جمله وجود داشته باشد.
اين امر سبب مي شود تا بعدا" بتوان براحتي دستور ديگري را اضافه نمود و نگراني
از فراموش كردن ابروها نخواهيد داشت . در حقيقت ، فراموش كردن تعريف يك بلوك
هنگامي كه نياز است ، يكي از دلايل رايج بروز خطاها مي باشد . بعنوان مثال قطعه
زير از يك كد را در نظر بگيريد :

+ int bytesAvailable;
+ //...
+ if( bytesAvailable > 0 ){
+ ProcessData)(;
+ bytesAvailable- = n;
+ } else
+ waitForMoreData)(;
+ bytesAvailable = n;


بنظر خيلي روشن است كه دستور bytes Available=n طوري طراحي شده تا داخل
جمله else اجرا گردد ، و اين بخاطر سطح طراحي آن است . اما حتما" بياد داريد
كه فضاي خالي براي جاوا اهميتي ندارد و راهي وجود ندارد كه كامپايلر بفهمد چه
مقصودي وجود دارد . اين كد بدون مشكل كامپايل خواهد شد ، اما هنگام اجرا بطور
ناصحيح اجرا خواهد شد . مثال بعدي داخل كدي كه مشاهده مي كنيد تثبيت شده است :

+ int bytesAvailable;
+ //...
+ if( bytesAvailable > 0 ){
+ ProcessData)(;
+ bytesAvailable- = n;
+ } else {
+ waitForMoreData)(;
+ bytesAvailable = n;
+ }
if

هاي تودرتو شده Nested ifs
يك nested if يك دستور if است كه هدف ifيا elseا ديگري باشد. if هاي تودرتو
در برنامه نويسي بسيار رايج هستند. هنگاميكه if ها را تودرتو مي كنيد، مهمترين
چيزي كه بايد بخاطر بسپاريد اين است كه يك دستورelse هميشه به نزديكترين دستور if
خود كه داخل همان بلوك else است و قبلا" با يك else همراه نشده ، مراجعه
خواهد نمود . مثالي را مشاهده نماييد :

+ if(i == 10 ){
+ if(j < 20 )a = b;
+ if(k > 100 )c = d; // this if is
+ else a = c; // associated with this else
+ }
+ else a = d; // this else refers to if(i == 10)


همانگونه كه توضيحات نشان مي دهند ، else نهايي با (20 چون داخل همان بلوك قرار ندارد ( اگر چه نزديكترين if بدون else است ) . بجاي
آن ، else نهايي با (i==10)if همراه مي شود . else داخلي به (100>k)if ارجاع
مي كند ، زيرا نزديكترين if در داخل همان بلوك است .

نردبان if-else-if
يك ساختار برنامه نويسي رايج براساس يك ترتيب از ifهاي تودرتو شده يا نردبان if-else-if
است . اين ساختار بصورت زير است :

if(condition)
statement;
else if(condition)

statement;
else if(condition)
statement;
.
.
.
else
statement;


دستورات if از بالا به پايين اجرا مي شوند . ماداميكه يكي از شرايط كنترل
كننده if صحيح باشد (true)، دستور همراه با آن if اجرا مي شود ، و بقيه نردبان
رد خواهد شد . اگر هيچكدام از شرايط صحيح نباشند، آنگاه دستور else نهايي اجرا
خواهد شد . else نهايي بعنوان شرط پيش فرض عمل مي كند ، يعني اگر كليه شرايط
ديگر صحيح نباشند ، آنگاه آخرين دستور else انجام خواهد شد . اگر else نهايي
وجود نداشته باشد و ساير شرايط ناصحيح باشند ، آنگاه هيچ عملي انجام نخواهد
گرفت .
در زير ، برنامه اي را مشاهده مي كنيد كه از نردبان if-else-if استفاده كرده
تا تعيين كند كه يك ماه مشخص در كدام فصل واقع شده است .

+ // Demonstrate if-else-if statement.
+ class IfElse {
+ public static void main(String args[] ){
+ int month = 4; // April
+ String season;
+
+ if(month == 12 || month == 1 || month == 2)
+ season = "Winter";
+ else if(month == 3 || month == 4 || month == 5)
+ season = "Spring";
+ else if(month == 6 || month == 7 || month == 8)
+ season = "Summer";
+ else if(month == 9 || month == 10 || month == 11)
+ season = "Autumn";
+ else
+ season = "Bogus Month";
+
+ System.out.println("April is in the" + season + ".");
+ }
+ }


خروجي اين برنامه بقرار زير مي باشد :

April is in the Spring.

ممكن است بخواهيد اين برنامه را تجربه نماييد . خواهيد ديد كه هيچ فرقي
ندارد كه چه مقداري به month بدهيد ، يك و فقط يك دستور انتساب داخل نردبان
اجرا خواهد شد .


switch


دستور switch ، دستور انشعاب چند راهه در جاوا است . اين دستور راه ساده اي
است براي تغيير مسير اجراي بخشهاي مختلف يك كد براساس مقدار يك عبارت . اين
روش يك جايگزين مناسب تر براي مجموعه هاي بزرگتر از دستورات if-else-if است .
شكل كلي دستور switch بقرار زير مي باشد :

switch(expression){
case value1:
// statement sequence
break;
case value2:
// statement sequence
break;
.
.
.
case valueN:
// statement sequence
break;
default:
// default statement sequence
}
expression

مي تواند هر نوع ساده اي را برگرداند ، هر يك از مقادير (values)
در دستورات case بايد از نوع سازگار با عبارت باشند . هر يك از مقادير case
بايد يك مقدار لفظي منحصر بفرد باشد ( يعني بايد يك ثابت ، نه متغير ، باشد ).
دو برابر سازي مقادير case مجاز نيست .
دستور switch بشرح فوق عمل مي كند : مقدار عبارت با هر يك از مقادير لفظي
در دستورات case مقايسه مي شوند. اگر تطابق پيدا شود ، كد سلسله اي تعقيب كننده
آن دستور case اجرا خواهد شد . اگر هيچيك از ثابت ها با مقدار عبارت تطابق
نيابند ، آنگاه دستور پيش فرض (default) اجرا خواهد شد ، اما دستور default
اختياري است . اگر هيچيك از case ها تطابق نيابد و default وجود نداشته باشد
آنگاه عمل اضافي ديگري انجام نخواهد شد .
از دستور break داخل دستور switch استفاده شده تا سلسله يك دستور را پايان
دهد . هنگاميكه با يك دستور break مواجه مي شويم ، اجرا به خط اول برنامه كه
بعد از كل دستور switch قرار گرفته ، منشعب خواهد شد . اين حالت تاثير پريدن switch
است .
در زير مثال ساده اي را مشاهده مي كنيد كه از دستور switch استفاده نموده
است :

+ // A simple example of the switch.
+ class SampleSwitch {
+ public static void main(String args[] ){
+ for(int i=0; i<6; i++)
+ switch(i ){
+ case 0:
+ System.out.println("i is zero.");
+ break;
+ case 1:
+ System.out.println("i is one.");
+ break;
+ case 2:
+ System.out.println("i is two.");
+ break;
+ case 3:
+ System.out.println("i is three.");
+ break;
+ default:
+ System.out.println("i is greater then 3.");
+ }
+ }
+ }


خروجي اين برنامه بقرار زير مي باشد :

i is zero.
i is one.
i is two.
i is three.
i is greater than 3.
i is greater than 3.


همانطوريكه مشاهده مي كنيد ، داخل حلقه ، دستوراتي كه همراه ثابت case بوده
و با i مطابقت داشته باشند ، اجرا خواهند شد . ساير دستورات پشت سر گذاشته
مي شوند (bypassed) . بعد از اينكه i بزرگتر از 3 بشود ، هيچ دستور همراه case
مطابقت نداشته ، بنابراين دستور پيش فرض (default) اجرا خواهد شد .
دستور break اختياري است . اگر break را حذف كنيد ، اجراي برنامه با case
بعدي ادامه خواهد يافت . گاهي بهتر است چندين case بدون دستورات break در بين
آنها داشته باشيم . بعنوان مثال ، برنامه بعدي را در نظر بگيريد :

+ // In a switch/ break statements are optional.
+ class MissingBreak {
+ public static void main(String args[] ){
+ for(int i=0; i<12; i++)
+ switch(i ){
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ System.out.println("i is less than 5");
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ System.out.println("i is less than 10");
+ break;
+ default:
+ System.out.println("i is 10 or more");
+ }
+ }
+ }


خروجي اين برنامه بقرار زير خواهد بود :

i is less than 5
i is less than 5
i is less than 5
i is less than 5
i is less than 5
i is less than 10
i is less than 10
i is less than 10
i is less than 10
i is less than 10
i is 10 or more
i is 10 or more


همانطوريكه مشاهده مي كنيد، اجرا طي هر case، بمحض رسيدن به يك دستور break
( يا انتهاي switch ) متوقف مي شود .
در حاليكه مثال قبلي براي توصيف نظر خاصي طراحي شده بود ، اما بهر حال حذف
دستور break كاربردهاي عملي زيادي در برنامه هاي واقعي دارد . براي نشان دادن
كاربردهاي واقعي تر اين موضوع ، دوباره نويسي برنامه نمونه مربوط به فصول سال
را مشاهده نماييد . اين روايت جديد همان برنامه قبلي از switch استفاده مي كند
تا پياده سازي موثرتري را ارائه دهد .

+ // An improved version of the season program.
+ class Switch {
+ public static void main(String args[] ){
+ int month = 4;
+ String season;
+ switch( month ){
+ case 12:
+ case 1:
+ case 2:
+ season = "Winter";
+ break;
+ case 3:
+ case 4:
+ case 5:
+ season = "Spring";
+ break;
+ case 6:
+ case 7:
+ case 8:
+ season = "Summer";
+ break;
+ case 9:
+ case 10:
+ case 11:
+ season = "Autumn";
+ break;
+ default:
+ season = "Bogus Month";
+ }
+ System.out.println("April is in the" + season + ".");
+
+ }
+ }



تودرتو كردن دستورات switch
مي توانيد از يك switch بعنوان بخشي از ترتيب يك دستور switch خارجي تر
استفاده نماييد. اين حالت را switch تودرتو مينامند. از آنجاييكه دستور switch
تعريف كننده بلوك مربوط به خودش مي باشد، هيچ تلاقي بين ثابتهاي caseدر switchر
داخلي و آنهايي كه در switch خارجي قرار گرفته اند ، بوجود نخواهد آمد . بعنوان
مثال ، قطعه بعدي كاملا" معتبر است .

+ switch(count ){
+ case 1:
+ switch(target ){ // nested switch
+ case 0:
+ System.out.println("target is zero");
+ break;
+ case 1 :// no conflicts with outer switch
+ System.out.println("target is one");
+ break;
+ }
+ break;
+ case 2 ://...


در اينجا دستور :case 1در switchر داخلي با دستور :case 1در switchر خارجي
تلاقي نخواهد داشت . متغير count فقط با فهرست case ها در سطح خارجي مقايسه
مي شود. اگر count برابر 1 باشد، آنگاه target با فهرست case هاي داخلي مقايسه
خواهد شد .
بطور خلاصه ، سه جنبه مهم از دستور switch قابل توجه هستند :
ؤ switchبا ifا متفاوت است چون switch فقط آزمايش كيفيت انجام مي دهد ، در
حاليكه if هر نوع عبارت بولي را ارزيابي مي كند . يعني كه switch فقط بدنبال
يك تطابق بين مقدار عبارت و يكي از ثابت هاي case خودش مي گردد .
ؤ دو ثابت caseدر switchر مشابه نمي توانند مقادير يكسان داشته باشند .
البته ، يك دستور switch قرار گرفته داخل يك switch خارجي تر مي تواند ثابتهاي case
مشترك داشته باشد .
ؤ يك دستور switch معمولا" بسيار كاراتر از يك مجموعه از if هاي تودرتو شده
است . آخرين نكته بخصوص جالب توجه است زيرا روشنگر نحوه كار كامپايلر جاوا
مي باشد . كامپايلر جاوا هنگاميكه يك دستور switch را كامپايل مي كند ، به هر
يك از ثابتهاي case سركشي نموده و يك جدول jump table مي سازد كه براي انتخاب
مسير اجرا براساس مقدار موجود در عبارت استفاده مي شود . بنابراين ، اگر بايد
از ميان گروه بزرگي از مقادير انتخاب نماييد ، يك دستور switch نسبت به يك
ترتيب از if-else ها كه بطور معادل و منطقي كد بندي شده باشد ، بسيار سريعتر
اجرا خواهد شد. كامپايلر قادر است اينكار را انجام دهد چون مي داند كه ثابتهاي case
همه از يك نوع بوده و بايد خيلي ساده با عبارت switch براي كيفيت مقايسه
شوند . كامپايلر چنين شناسايي را نسبت به يك فهرست طولاني از عبارات if ندارد .

دستورات تكرار iteration statements
دستورات تكرار در جاوا عبارتند از for، while،و do-whileو . اين دستورات آن
چه را ما " حلقه " مي ناميم ، ايجاد مي كنند . احتمالا" مي دانيد كه حلقه يك
مجموعه از دستورالعملها را بطور تكراري اجرا مي كند . تا اينكه يك شرط پاياني
را ملاقات نمايد . همانطوريكه بعدا" خواهيد ديد، جاوا حلقه اي دارد كه براي كليه
نيازهاي برنامه نويسي مناسب است .


while


حلقه while اساسي ترين دستور حلقه سازي (looping) در جاوا است . اين دستور
ماداميكه عبارت كنترل كننده ، صحيح (true) باشد، يك دستور يا يك بلوك را تكرار
مي كند . شكل كلي اين دستور بقرار زير است :

while(condition ){
// body of loop
}


شرط يا condition ممكن است هر عبارت بولي باشد . ماداميكه عبارت شرطي صحت
داشته باشد ، بدنه حلقه اجرا خواهد شد . هنگاميكه شرط صحت نداشته باشد ، كنترل
بلافاصله به خط بعدي كدي كه بلافاصله پس از حلقه جاري قرار دارد ، منتقل خواهد
شد . اگر فقط يك دستور منفرد در حال تكرار باشد ، استفاده از ابروها غير ضروري
است .
در اينجا يك حلقه while وجود دارد كه تا 10 را محاسبه كرده و دقيقا" ده خط "tick"
را چاپ مي كند .

+ // Demonstrate the while loop.
+ class While {
+ public static void main(String args[] ){
+ int n = 10;
+
+ while(n > 0 ){
+ System.out.println("tick" + n);
+ n--;
+ }
+ }
+ }


هنگاميكه اين برنامه را اجرا مي كنيد، ده مرتبه "tick" را انجام خواهد داد:

tick 10
tick 9
tick 8
tick 7
tick 6
tick 5
tick 4
tick 3
tick 2
tick 1


از آنجاييكه حلقه while عبارت شرطي خود را در بالاي حلقه ارزيابي ميكند، اگر
شرط ابتدايي ناصحيح باشد ، بدنه حلقه اجرا نخواهد شد . بعنوان مثال ، در قطعه
زير ، فراخواني ()println هرگز اجرا نخواهد شد .

+ int a = 10/ b = 20;
+
+ while(a < b)
+ System.out.println("This will not be displayed");


بدنه while ( يا هر حلقه ديگر در جاوا ) ممكن است تهي باشد. زيرا دستور تهي
( دستوري كه فقط شامل ; باشد ) از نظر قواعد تركيبي در جاوا معتبراست . بعنوان
مثال ، برنامه زير را در نظر بگيريد :

+ // The target of a loop can be empty.
+ class NoBody {
+ public static void main(String args[] ){
+ int i/ j;
+
+ i = 100;
+ j = 200;
+
+ // find midpoint between i and j
+ while(++i <-- j); // no body in this loop
+
+ System.out.println("Midpoint is" + i);
+ }
+ }


اين برنامه نقطه مياني (midpoint) بين iو jو را پيدا مي كند و خروجي زير را
توليد خواهد كرد :

Midpoint is 150


در اينجا چگونگي كار حلقه while را مي بينيد . مقدار i افزايش و مقدار j
كاهش مي يابد . سپس اين دو مقدار با يكديگر مقايسه مي شوند . اگر مقدار جديد i
همچنان كمتر از مقدار جديد j باشد ، آنگاه حلقه تكرار خواهد شد . اگر i مساوي
با يا بزرگتر از j بشود ، حلقه متوقف خواهد شد . تا هنگام خروج از حلقه ، i
مقداري را مي گيرد كه بين مقادير اوليه iو jو مي باشد . ( بديهي است كه اين
رويه هنگامي كار مي كند كه i كوچكتر از مقدار اوليه j باشد . ) همانطوريكه
مي بينيد ، نيازي به بدنه حلقه نيست ، كليه عمليات داخل خود عبارت شرطي اتفاق
مي افتد . در كدهاي حرفه اي نوشته شده ديگر جاوا ، وقتي كه عبارت كنترل كننده
توانايي مديريت كليه جزئيات خود را داشته باشد ، حلقه هاي كوتاه غالبا" بدون
بدنه كد بندي مي شوند .


do-while


گفتيم اگر عبارت شرطي كنترل كننده يك حلقه while در ابتدا ناصحيح باشد
آنگاه بدنه حلقه اصلا" اجرا نمي شود . اما گاهي مايليم در چنين شرايطي ، بدنه
حلقه حداقل يكبار اجرا شود . بعبارت ديگر، در حالات خاصي مايليد تا عبارت پايان
دهنده در انتهاي حلقه را آزمايش كنيد. خوشبختانه ، جاوا حلقه اي را عرضه مي كند
كه دقيقا" همين كار را انجام مي دهد : do-while . حلقه do-while همواره حداقل
يكبار بدنه خود را اجرا مي كند، زيرا عبارت شرطي آن در انتهاي حلقه قرار گرفته
است . شكل كلي آن بصورت زير است :

do{
// body of loop
} while(condition);


هر تكرار از حلقه do-while ابتدا بدنه حلقه را اجرا نموده ، سپس به ارزيابي
عبارت شرطي خود مي پردازد . اگر اين عبارت صحيح (true) باشد ، حلقه اجرا خواهد
شد . در غير اينصورت حلقه پايان مي گيرد . نظير كليه حلقه هاي جاوا ، شرط بايد
يك عبارت بولي باشد .
اينجا يك روايت ديگر از برنامه (tick) وجود دارد كه حلقه do-while را نشان
مي دهد . خروجي اين برنامه مشابه برنامه قبلي خواهد بود :

+ // Demonstrate the do-while loop.
+ class DoWhile {
+ public static void main(String args[] ){
+ int n = 10;
+
+ do {
+ System.out.println("tick" + n);
+ n--;
+ } while(n > 0);
+ }
+ }


حلقه موجود در برنامه قبلي ، اگر چه از نظر تكنيكي صحيح است ، اما مي توان
آن را به شكل كاراتري بصورت زير دوباره نويسي نمود : + do {
+ System.out.println("tick " + n);
+ } while--(n > 0);

در اين مثال ، عبارت (0>n) عمل كاهش n و آزمايش براي صفر را در يك عبارت
گنجانده است . عملكرد آن بقرار بعدي است . ابتدا دستور n اجرا مي شود و n
را كاهش داده و مقدار جديد را به n برمي گرداند . اين مقدار سپس با صفر مقايسه
مي شود . اگر بزرگتر از صفر باشد ، حلقه ادامه مي يابد . در غير اينصورت حلقه
پايان مي گيرد .
حلقه do-while بويژه هنگام پردازش انتخاب منو بسيار سودمند است ، زيرا
معمولا" مايليد تا بدنه يك حلقه منو حداقل يكبار اجرا شود . برنامه بعدي را كه
يك سيستم Help ساده را براي دستورات تكرار و انتخاب در جاوا پياده سازي مي كند
در نظر بگيريد :

+ // Using a do-while to process a menu selection -- a simple help system.
+ class Menu {
+ public static void main(String args[])
+ throws java.io.IOException {
+ char choice;
+
+ do {
+ System.out.prinln("Help on:");
+ System.out.prinln(" 1 .if");
+ System.out.prinln(" 2 .switch");
+ System.out.prinln(" 3 .while");
+ System.out.prinln(" 4 .do-while");
+ System.out.prinln(" 5 .for\n");
+ System.out.prinln("Choose one:");
+ choice =( char )System.in.read)(;
+ } while(choice < '1' || choice > '5');
+
+ System.out.println("\n");
+ switch(choice ){
+ case '1':
+ System.out.println("The if:\n");
+ System.out.println("if(condition )statement;");
+ System.out.println("else statement;");
+ break;
+ case '2':
+
+ System.out.println("The switch:\n");
+ System.out.println("switch(expression ){");
+ System.out.println(" case constant:");
+ System.out.println(" statement sequence");
+ System.out.println(" break;");
+ System.out.println(" //... ");
+ System.out.println("}");
+ break;
+ case '3':
+ System.out.println("The switch:\n");
+ System.out.println(while(condition )statement;");
+ break;
+ case '4':
+ System.out.println("The do-while:\n");
+ System.out.println("do {");
+ System.out.println(" statement;");
+ System.out.println("} while( condition);");
+ break;
+ case '5':
+ System.out.println("The for:\n");
+ System.out.print("for(init; condition; iteration)");
+ System.out.println(" statement;");
+ break;
+ }
+ }
+ }


اكنون يك اجراي نمونه توليد شده توسط اين برنامه را مشاهده مي كنيد :

Help on:
1 .if
2 .switch
3 .while
4 .do-while
5 .for
Choos one:
4

The do-while:

do {
statement;
} while( condition);


در برنامه ، از حلقه do-while براي تصديق اينكه كاربر يك گزينه معتبر را
وارد كرده باشد ، استفاده مي شود . در غير اينصورت ، به كاربر مجددا" اعلان
خواهد شد . از آنجاييكه منو بايد حداقل يكبار بنمايش درآيد ، do-while حلقه
كاملي براي انجام اين مقصود است .
چند نكته ديگر درباره اين مثال : دقت كنيد كه كاراكترهااز صفحه كليد بوسيله
فراخواني ()system.in.read خوانده مي شوند . اين يكي از توابع ورودي كنسول در
جاوا است .
اگر چه بررسي تفصيلي روشهاي l/o جاوا به بحثهاي بعدي موكول شده ، اما از
()system.in.read در اينجا براي بدست آوردن گزينه كاربر استفاده شده است . اين
تابع كاراكترها را از ورودي استاندارد مي خواند ( كه بعنوان عدد صحيح برگردان
شد ، اين دليلي است كه چرا مقدار برگردان از طريق تبديل (cast) به char تبديل
شده است ). بصورت پيش فرض ، ورودي استاندارد، بافر شده خطي است (line buffered)
بنابراين قبل از اينكه كاراكترهايي را كه تايپ كرده ايد به برنامه اتان ارسال
كنيد ، بايد كليد ENTER را فشار دهيد . ( اين حالت مشابه C++/C است و احتمالا"
از قبل با آن آشنايي داريد ) .
ورودي كنسول در جاوا كاملا" محدود شده و كار با آن بسيار مشكل است . بعلاوه
اكثر برنامه و ريز برنامه هاي واقعي نوشته شده با جاوا گرافيكي و پنجره اي
هستند. از سوي ديگر : چون از ()system.in.read استفاده شده ، برنامه بايد جمله throwsjava.io.loException
را كاملا" توصيف نمايد . اين خط براي مديريت خطاهاي
ورودي ضروري است . اين بخشي از جنبه هاي مختلف اداره استثنائ در جاوا است كه
بعدا" بررسي خواهد شد .
for

خواهيد ديد كه حلقه for يك ساختار قدرتمند و بسيار روان است .شكل كلي دستور for
بصورت زير است :

for(initialization; condition; iteration; ){
// body
}


اگر فقط يك دستور بايد تكرار شود ، نيازي به ابروها نيست .
عملكرد حلقه for بشرح بعدي است . وقتي كه حلقه براي اولين بار شروع مي شود
بخض مقدار دهي اوليه در حلقه اجرا مي شود . معمولا" ، اين بخش يك عبارت است كه
مقدار متغير كنترل حلقه را تعيين مي كند ، كه بعنوان يك شمارشگر ، كنترل حلقه
را انجام خواهد داد . مهم است بدانيم كه عبارت مقدار دهي اوليه فقط يكبار اجرا
مي شود . سپس شرط مورد ارزيابي قرار مي گيرد . اين شرط بايد يك عبارت بولي
باشد . اين بخش معمولا" مقدار متغير كنترل حلقه را با مقدار هدف مقايسه مي كند.
اگر عبارت صحيح (true) باشد، آنگاه بدنه حلقه اجرا خواهد شد . اگر ناصحيح باشد
حلقه پايان مي گيرد . بعد، بخش تكرار (iteration) حلقه اجرا مي شود . اين بخش
معمولا" عبارتي است كه مقدار متغير كنترل را افزايش يا كاهش مي دهد. آنگاه حلقه
تكرار خواهد شد ، ابتدا عبارت شرطي را ارزيابي مي كند ، سپس بدنه حلقه را اجرا
مي كند و سرانجام عبارت تكرار را در هر گذر (pass) اجرا ميكند. اين روال آنقدر
دادمه مي يابد تا عبارت شرطي ناصحيح (false) گردد .
در زير روايت جديدي از برنامه "tick" را مي بينيد كه از يك حلقه for استفاده
كرده است :

+ // Demonstrate the for loop.
+ class ForTick {
+ public static void main(String args[] ){
+ int n;
+ for(n=10; n>0; n)--
+ System.out.println("tick" + n);
+ }
+ }



اعلان متغيرهاي كنترل حلقه داخل حلقه for
غالبا" متغيري كه يك حلقه for را كنترل مي كند ، فقط براي همان حلقه مورد
نياز بوده و كاربري ديگري ندارد . در چنين حالتي ، مي توان آن متغير را داخل
بخش مقدار دهي اوليه حلقه for اعلان نمود . بعنوان مثال در اينجا همان برنامه
قبلي را مشاهده مي كنيد كه متغير كنترل حلقه يعني n بعنوان يك int در داخل
حلقه for اعلان شده است .

+ // Declare a loop control variable inside the for.
+ class ForTick {
+ public static void main(String args[] ){
+
+ // here/ n is declared inside of the for loop
+ for(int n=10; n>0; n)--
+ System.out.println("tick" + n);
+ }
+ }


هنگاميكه يك متغير را داخل يك حلقه for اعلان مي كنيد ، يك نكته مهم را بايد
بياد داشته باشيد : قلمرو آن متغير هنگاميكه دستور for انجام مي شود ، پايان
مي يابد . ( يعني قلمرو متغير محدود به حلقه for است . ) خارج از حلقه for
حيات آن متغير متوقف مي شود . اگر بخواهيد از اين متغير كنترل حلقه در جاي
ديگري از برنامه اتان استفاده كنيد ، نبايد آن متغير را داخل حلقه for اعلان
نماييد .
درشرايطي كه متغير كنترل حلقه جاي ديگري موردنياز نباشد، اكثر برنامه نويسان
جاوا آن متغير را داخل for اعلان مي كنند . بعنوان مثال ، در اينجا يك برنامه
ساده را مشاهده مي كنيد كه بدنبال اعداد اول مي گردد. دقت كنيد كه متغير كنترل
حلقه ، چون جاي ديگري مورد نياز نيست ، داخل for اعلان شده است .

+ // Test for primes.
+ class FindPrime {
+ public static void main(String args[] ){
+ int num;
+ boolean isPrime = true;
+
+ num = 14;
+ for(int i=2; i < num/2; i++ ){
+ if((num % i )== 0 ){
+ isPrime = false;
+ break;
+ }
+ }
+ if(isPrime )System.out.println("Prime");
+ else System.out.println("Not Prime");
+ }
+ }


استفاده از كاما Comma
شرايطي پيش مي آيد كه مايليد بيش از يك دستور در بخش مقدار دهي اوليه
(initalization) و تكرار (iteration) بگنجانيد . بعنوان مثال ، حلقه موجود در
برنامه بعدي را در نظر بگيريد :

+ class Sample {
+ public static void main(String args[] ){
+ int a/ b;
+
+ b = 4;
+ for(a=1; a + System.out.println("a = " + a);
+ System.out.println("b = " + b);
+ b--;
+ }
+ }
+ }


همانطوريكه مي بينيد ، حلقه توسط ارتباط متقابل دو متغير كنترل مي شود . از
آنجاييكه حلقه توسط دو متغير اداره مي شود ، بجاي اينكه b را بصورت دستي اداره
كنيم ، بهتر است تا هر دو را در دستور for بگنجانيم . خوشبختانه جاوا راهي
براي اينكار دارد . براي اينكه دو يا چند متغير بتوانند يك حلقه for را كنترل
كنند ، جاوا به شما امكان مي دهد تا چندين دستور را در بخشهاي مقدار دهي اوليه
و تكرار حلقه for قرار دهيد . هر دستور را بوسيله يك كاما از دستور بعدي جدا
مي كنيم .
حلقه for قبلي را با استفاده از كاما ، خيلي كاراتر از قبل مي توان بصورت
زير كد بندي نمود :

+ // Using the comma.
+ class Comma {
+ public static void main(String args[] ){
+ int a/ b;
+
+ for(a=1/ b=4; a + System.out.println("a = " + a);
+ System.out.println("b = " + b);
+ }
+ }
+ }


در اين مثال ، بخش مقدار دهي اوليه ، مقادير aو bو را تعيين مي كند . هربار
كه حلقه تكرار مي شود ، دو دستور جدا شده توسط كاما در بخش تكرار (itration)
اجرا خواهند شد . خروجي اين برنامه بقرار زير مي باشد :

a=1
b=4
a=2
b=3


نكته : اگر با C++/C آشنايي داريد ، حتما" مي دانيد كه در اين زبانها ، علامت
كاما يك عملگر است كه در هر عبارت معتبري قابل استفاده است . اما در
جاوا اينطور نيست . در جاوا ، علامت كاما يك جدا كننده است كه فقط در
حلقه for قابل اعمال مي باشد .

برخي گوناگونيهاي حلقه for
حلقه for از تعدادي گوناگونيها پشتيباني مي كند كه قدرت و كاربري آن را
افزايش مي دهند . دليل انعطاف پذيري آن است كه لزومي ندارد كه سه بخش مقداردهي
اوليه ، آزمون شرط و تكرار ، فقط براي همان اهداف مورد استفاده قرار گيرند .
در حقيقت ، سه بخش حلقه for براي هر هدف مورد نظر شما قابل استفاده هستند . به
چند مثال توجه فرمائيد .
يكي از رايجترين گوناگونيها مربوط به عبارت شرطي است . بطور مشخص ، لزومي
ندارد اين عبارت ، متغير كنترل حلقه را با برخي مقادير هدف آزمايش نمايد . در
حقيقت ، شرط كنترل كننده حلقه for ممكن است هر نوع عبارت بولي باشد . بعنوان
مثال ، قطعه زير را در نظر بگيريد :

+ boolean done = false;
+
+ for(int i=1; !done; i++ ){
+ //...
+ if(intettupted ))(done = true;
+ }


در اين مثال ، حلقه for تا زمانيكه متغير بولي done معادل true بشود ، اجرا
را ادامه خواهد داد . اين مثال مقدار i را بررسي نمي كند .
اكنون يكي ديگر از گوناگونيهاي جالب حلقه for را مشاهده مي كنيد. ممكن است
يكي يا هر دو عبارت مقدار دهي اوليه و تكرار غايت باشند ، نظير برنامه بعدي :

+ // Parts of the for loop can be empty.
+ class ForVar {
+ public static void main(String args[] ){
+ int i;
+ boolean done = false;
+
+ i = 0;
+ for (; !done; ) {
+ System.out.println("i is" + i);
+ if(i == 10 )done = true;
+ i++;
+ }
+ }
+ }


در اينجا عبارتهاي مقدار دهي اوليه و تكرار به خارج ازfor انتقال يافته اند.
برخي از بخشهاي حلقه for تهي هستند . اگر چه در اين مثال ساده چنين حالتي هيچ
ارزشي ندارد ، اما در حقيقت شرايطي وجود دارد كه اين روش بسيار كارا و سودمند
خواهد بود. بعنوان مثال ، اگر شرط اوليه بصورت يك عبارت پيچيده و در جاي ديگري
از برنامه قرار گرفته باشد و يا تغييرات متغير كنترل حلقه بصورت غير ترتيبي و
توسط اعمال اتفاق افتاده در داخل بدنه حلقه تعيين شود ، پس بهتر است كه اين
بخشها را در حلقه for تهي بگذاريم .
اكنون يكي ديگر از گوناگونيهاي حلقه for را مشاهده مي كنيد. اگر هر سه بخش
حلقه for را تهي بگذاريد ، آنگاه بعمد يك حلقه نامحدود ( حلقه اي كه هرگز پايان
نمي گيرد ) ايجاد كرده ايد . بعنوان مثال :

+ for (; ; ) {
+ //...
+ }


اين حلقه تا ابد ادامه خواهد يافت ، زيرا هيچ شرطي براي پايان گرفتن آن
تعبيه نشده است . اگر چه برخي برنامه ها نظير پردازشهاي فرمان سيستم عامل
مستلزم يك حلقه نامحدود هستند ، اما اكثر حلقه هاي نامحدود در واقع حلقه هايي
هستند كه ملزومات پايان گيري ويژه اي دارند . بزودي خواهيد ديد ، راهي براي
پايان دادن به يك حلقه حتي يك حلقه نامحدود نظير مثال قبلي وجود دارد كه
از عبارت شرطي معمولي حلقه استفاده نمي كند .

حلقه هاي تودرتو
نظير كليه زبانهاي برنامه نويسي ، جاوا نيز امكان تودرتو كردن حلقه ها را
دارد . يعني يك حلقه داخل حلقه ديگري قرار خواهد گرفت . بعنوان مثال ، در
برنامه بعدي حلقه هاي for تودرتو نشده اند :

+ // Loops may be nested.
+ class Nested {
+ public static void main(String args[] ){
+ int i/ j;
+
+ for(i=0; i<10; i++ ){
+ for(j=i; j<10; j++)
+ System.out.print(".");
+ System.out.println)(;
+ }
+ }
+ }


خروجي توليد شده توسط اين برنامه بقرار زير مي باشد : ..........
.........

Nesta
01-07-2005, 07:29
دومين برنامه كوتاه

شايد در يك زبان برنامه نويسي هيچ مفهومي اساسي تر از يك متغير (Variable)
نباشد. به احتمال زياد مي دانيد كه يك متغير مكاني از حافظه نامگذاري شده است
كه توسط برنامه شما مقداري به آن نسبت داده مي شود . مقدار يك متغير ممكن است
حين اجراي يك برنامه تغيير يابد . برنامه بعدي نشان مي دهد كه چگونه يك متغير
را اعلان نموده و چگونه مقداري را به آن نسبت مي دهيم . علاوه بر اين ، برنامه
همچنين نشاندهنده برخي جنبه هاي خروجي كنسول نيز ميباشد. همانطوريكه " توضيحات "
در بالاي برنامه بيان مي كنند ، بايد اين فايل را Example2.java بناميد .

+ /*
+ Here is another short example.
+ Call this file "Example2.java".
+ */
+ class Example2 {
+ public static void main(String args [] ){
+ int num; // this declares a variable called num
+ num = 100; // this assigns num the value 100
+ System.out.println("This is num :" + num);
+ num = num * 2;
+ System.out.print("The value of num * 2 is *);
+ System.out.println(num);
+ }
+ }


هنگاميكه اين برنامه را اجرا كنيد ، خروجي زير را مشاهده مي كنيد : This is num :100
The value of num * 2 is 200

اكنون نگاه دقيقتري به چگونگي توليد اين خروجي خواهيم داشت . اولين خط جديد
برنامه را در زير نشان داده ايم :

+ int num; // this declares a variable called num


اين خط يك متغير عدد صحيح تحت نام num را اعلان مي كند . جاوا ( نظير اكثر
زبانهاي برنامه نويسي ) ايجاب مي كند كه متغيرها قبل از اينكه مورد استفاده
قرار گيرند ، بايد تعريف شوند .
شكل عمومي براي اعلان يك متغير را مشاهده مي كنيد :

type var-name;


در اينجا type مشخص كننده نوع متغيري است كه اعلان خواهد شد، و var-name نام
آن متغير است . اگر مي خواهيد بيش از يك متغير از آن نوع مشخص شده اعلان كنيد
مي توانيد با استفاده از فهرست كاما (comma) اسامي متغيرها را جدا كنيد . جاوا
چندين نوع داده را تعريف مي كند كه دربرگيرنده اعداد صحيح (integer) ، كاراكتر
(character) و اعشاري (floating-point) مي باشد . واژه كليدي int مشخص كننده
نوع عدد صحيح است .
در برنامه ، خط زير :

+ num = 100; // this assigns num the value 100


مقدار 100 را به متغير num نسبت مي دهد. در جاوا، عملگر (operator) انتساب
يك علامت تساوي تكي (=) است .
خط بعدي كد ، مقدار متغير num را بعنوان خروجي ارائه داده و البته قبل از
اين مقدار رشته "This is num" قرار خواهد گرفت .

+ System.out.println("This is num :" + num);


در اين دستور ، علامت تساوي سبب مي شود تا مقدار متغير num با رشته اي كه قبل
از آن قرار مي گيرد پيوسته باشد ، و رشته حاصل سرانجام خروجي خواهد شد . ( در
واقع ، num ابتدا از شكل يك عدد صحيح به معادل رشته اي خود تبديل شده و سپس به
رشته قبل از خود پيوسته خواهد شد . اين رويه بعدا" بررسي خواهد شد. ) اين شيوه
را مي توان عمومي نمود. با استفاده از عملگر + ، مي توانيد هر تعداد اقلام مورد
نظرتان را در داخل يك دستور تكي ()println به رشته درآوريد .
خط بعدي كد ، مقدار متغير num را در 2 ضرب نموده و حاصل را به متغير num
نسبت مي دهد . نظير اكثر زبانهاي برنامه نويسي ، جاوا از عملگر * براي نشان
دادن عمل ضرب استفاده مي كند . بعد از اينكه اين خط اجرا شود ، متغير num دربر
گيرنده مقدار 200 خواهد بود .
اكنون دو خط بعدي برنامه را بررسي مي كنيم :

+ System.out.print("This value of num * 2 is ");
+ System.out.println(num);


چند مورد جديد اينجا در حال وقوع است . اول اينكه از روش توكار ()print
استفاده شده تا رشته "The value of num *2 is" بنمايش درآيد . بعد از اين رشته
يك خط جديد نخواهد آمد. اين بدان معني است كه وقتي خروجي بعدي توليد شود، همان
خط شروع خواهد شد . روش ()print مشابه روش ()println مي باشد ، بجز اينكه آن
روش اول بعد از هر فراخواني يك كاراكتر خط جديد خارج نخواهد كرد . اكنون به
فراخواني ()println نگاه كنيد . دقت كنيد كه متغير num توسط خودش مورد استفاده
قرار مي گيرد . هم ()print و هم ()println را مي توان براي خروجي مقادير هر يك تفاده قرار داد .

Nesta
01-07-2005, 07:30
معرفي كلاسها

كلاس هسته اصلي جاوا است . كلاس يك ساختار منطقي است كه تماميت زبان جاوا بر
آن استوار شده ، زيرا شكل (shape) و طبيعت يك شي ئ را روشن مي كند . كلاس همچنين
شكل دهنده اساس برنامه نويسي شي ئ گرا در جاوا مي باشد. هر مفهومي كه مايليد در
يك برنامه جاوا پياده سازي نماييد بايد ابتدا داخل يك كلاس كپسول سازي شود .
از اين پس مي آموزيد چگونه يك كلاس را براي توليد اشيائاستفاده كنيد. همچنين
درباره روشها (methods) و سازنده ها (constructors) و واژه كليدي this مطالبي
مي آموزيد .

Nesta
01-07-2005, 07:31
بنيادهاي كلاس

كلاسهاي توليد شده در بحثهاي گذشته فقط براي كپسول سازي روش ()main استفاده
مي شد ، كه براي نشان دادن اصول دستور زبان جاوا مناسب بودند . شايد بهترين
چيزي كه بايد درباره يك كلاس بدانيد اين است كه كلاس يك نوع جديد داده را تعريف
مي كند . هربار كه اين نوع تعريف شود ، مي توان از آن براي ايجاد اشيائي از
همان نوع استفاده نمود . بنابراين ، يك كلاس قالبي (template) براي يك شي ئ است
و يك شي ئ نمونه اي (instance) از يك كلاس است . چون شي ئ يك نمونه از يك كلاس است
غالبا" كلمات شي ئ (object) و نمونه (instance) را بصورت مترادف بكار مي بريم .

شكل عمومي يك كلاس
هنگاميكه يك كلاس را تعريف مي كنيد ، در حقيقت شكل و طبيعت دقيق آن كلاس را
اعلان مي كنيد . ابتكار را با توصيف داده هاي موجود در آن كلاس و كدهايي كه روي
آن داده ها عمل مي كنند ، انجام مي دهيد . در حاليكه كلاسها ممكن است خيلي ساده
فقط شامل داده يا فقط كد باشند، اكثر كلاسهاي واقعي هردو موضوع را دربرميگيرند.
بعدا" خواهيد ديد كه كد يك كلاس ، رابط آن به داده هاي همان كلاس را توصيف ميكند.
يك كلاس را با واژه كليدي class اعلان مي كنند . كلاسهايي كه تا بحال استفاده
شده اند ، نوع بسيار محدود از شكل كامل كلاسها بوده اند . خواهيد ديد كه كلاسها
مي توانند ( و معمولا" هم ) بسيار پيچيده تر باشند . شكل عمومي توصيف يك كلاس به
شرح زير است :

type methodname2(parameter-list ){
// body of method
}
//...
type methodnameN(parameter-list ){
// body of method
}
}


داده يا متغيرهايي كه داخل يك كلاس تعريف شده اند را متغيرهاي نمونه instance)
(variables مي نامند . كدها ، داخل روشها (methods) قرار مي گيرند . روشها و
متغيرهاي تعريف شده داخل يك كلاس را اعضائ (members) يك كلاس مي نامند . در اكثر
كلاسها ، متغيرهاي نمونه يا روي روشهاي تعريف شده براي آن كلاس عمل كرده يا توسط
اين روشها مورد دسترسي قرار مي گيرند . بنابراين ، روشها تعيين كننده چگونگي
استفاده از داده هاي يك كلاس هستند .
متغيرهاي تعريف شده داخل يك كلاس ، متغيرهاي نمونه خوانده شده زيرا هر نمونه
از كلاس ( يعني هر شي ئ يك كلاس ) شامل كپي خاص خودش از اين متغيرهاست . بنابراين
داده مربوط به يك شي ئ ، جدا و منحصر بفرد از داده مربوط به شي ئ ديگري است . ما
بزودي اين نكته را بررسي خواهيم نمود ، اما فعلا" بايد اين نكته بسيار مهم را
بياد داشته باشيد .
كليه روشها نظير()main همان شكل عمومي را دارند كه تاكنون استفاده كرده ايم .
اما ، اكثر روشها را بعنوان staticيا publicا توصيف نمي كنند . توجه داشته
باشيد كه شكل عمومي يك كلاس ، يك روش ()main را توصيف نمي كند . كلاسهاي جاوا
لزومي ندارد كه يك روش ()main داشته باشند . فقط اگر كلاس ، نقطه شروع برنامه
شما باشد ، بايد يك روش ()main را توصيف نماييد . علاوه بر اين ، ريز برنامه ها
(applets) اصولا" نيازي به روش ()main ندارند .
نكته : برنامه نويسان C++ آگاه باشند كه اعلان كلاس و پياده سازي روشها در يك
مكان ذخيره شده و بصورت جداگانه تعريف نمي شوند. اين حالت گاهي فايلهاي
خيلي بزرگ java ايجاد مي كند ، زيرا هر كلاس بايد كاملا" در يك فايل منبع
تكي تعريف شود . اين طرح در جاوا رعايت شد زيرا احساس مي شد كه در بلند
مدت ، در اختيار داشتن مشخصات ، اعلانها و پياده سازي در يك مكان ، امكان
دسترسي آسانتر كد را بوجود مي آورد .

يك كلاس ساده
بررسي خود را با يك نمونه ساده از كلاسها شروع مي كنيم . در اينجا كلاسي تحت
غنوان Box وجود دارد كه سه متغير نمونه را تعريف مي كند : width، height، و depth
و فعلا" ، كلاس Box دربرگيرنده روشها نيست .

+ class Box {
+ double width;
+ double height;
+ double depth;
+ }


قبلا" هم گفتيم كه يك كلاس نوع جديدي از داده را توصيف مي كند . در اين مثال
نوع جديد داده را Box ناميده ايم . از اين نام براي اعلان اشيائ از نوع Box
استفاده مي كنيد . نكته مهم اين است كه اعلان يك كلاس فقط يك الگو يا قالب را
ايجاد مي كند ، اما يك شي ئ واقعي بوجود نمي آورد . بنابراين ، كد قبلي ، شيئي
از نوع Box را بوجود نمي آورد .
براي اينكه واقعا" يك شي ئ Box را بوجود آوريد ، بايد از دستوري نظير مورد
زير استفاده نماييد :

+ Box mybox = new Box)(; // create a Box object called mybox


پس از اجراي اين دستور ، mybox نمونه اي از Box خواهد بود. و بدين ترتيب اين
شي ئ وجود فيزيكي و واقعي پيدا مي كند .
مجددا" بياد داشته باشيد كه هر بار يك نمونه از كلاسي ايجاد مي كنيد ، شيئي
ايجاد كرده ايد كه دربرگيرنده كپي ( نسخه خاص ) خود از هر متغير نمونه تعريف
شده توسط كلاس خواهد بود . بدين ترتيب ، هر شي ئ Box دربرگيرنده كپي هاي خود از
متغيرهاي نمونه width، heidht،و depthو مي باشد . براي دسترسي به اين متغيرها
از عملگر نقطه (.) استفاده مي كنيد . عملگر نقطه اي ، نام يك شي ئ را با نام يك
متغير نمونه پيوند مي دهد . بعنوان مثال ، براي منتسب كردن مقدار 100 به متغير width
در myboxر ، از دستور زير استفاده نماييد :

+ mybox.width = 100;


اين دستور به كامپايلر مي گويد كه كپي width كه داخل شي ئ mybox قرار گرفته
را معادل عدد 100 قرار دهد . بطور كلي ، از عملگر نقطه اي براي دسترسي هم به
متغيرهاي نمونه و هم به روشهاي موجود در يك شي ئ استفاده مي شود .
دراينجا يك برنامه كامل را مشاهده ميكنيد كه از كلاس Box استفاده كرده است :

+ /* A program that uses the Box class.
+
+ Call this file BoxDemo.java
+ /*
+ class Box {
+ double width;
+ double height;
+ double depth;
+ }
+
+ // This class declares an object of type Box.
+ class BoxDemo {
+ public static void main(String args[] ){
+ Box mybox = new Box)(;
+ double vol;
+
+ // assign values to mybox's instance variables
+ mybox.width = 10;
+ mybox.height = 20;
+ mybox.depth = 15;
+
+ // compute volume of box
+ vol = mybox.width * mybox.height * mybox.depth;
+
+ System.out.println("Volume is " + vol);
+ }
+ }


فايلي را كه دربرگيرنده اين برنامه است بايد با نام BoxDemo.java بخوانيد
زيرا روش ()main در كلاس BoxDemo و نه در كلاس Box قرار گرفته است . هنگاميكه اين
برنامه را كامپايل مي كنيد ، مي بينيد كه دو فايل class. ايجاد شده اند ، يكي
براي Box و ديگري براي BoxDemo . كامپايلر جاوا بطور خودكار هر كلاس را در فايل class
. مربوط به خودش قرار مي دهد . ضرورتي ندارد كه كلاس Boxو BoxDemoو هر دو
در يك فايل منبع قرار گيرند . مي توانيد هر كلاس را در فايل خاص خودش گذاشته و
آنها را بترتيب Box.javaو BoxDemo.javaو بناميد .
براي اجراي اين برنامه بايد BoxDemo.class را اجرا كنيد . پس از اينكار
حاصل زير را بدست مي آوريد :

Volume is 3000


قبلا" هم گفتيم كه هر شي ئ داراي كپي هاي خاص خودش از متغيرهاي نمونه است .
يعني اگر دو شي ئ Box داشته باشيد، هركدام بتنهايي كپي ( يا نسخه اي ) از lenght width
و heightو خواهند داشت . مهم است بدانيد كه تغييرات در متغيرهاي نمونه يك
شي ئ تاثيري روي متغيرهاي نمونه كلاس ديگر نخواهد داشت . بعنوان مثال ، برنامه
بعدي دو شي ئ Box را اعلان مي كند :

+ // This program declares two Box objects.
+
+ class Box {
+ double width;
+ double height;
+ double depth;
+ }
+
+ class BoxDemo2 {
+ public static void main(String args[] ){
+
+ Box mybox1 = new Box)(;
+ Box mybox2 = new Box)(;
+ double vol;
+
+ // assign values to mybox1's instance variables
+ mybox1.width = 10;
+ mybox1.height = 20;
+ mybox1.depth = 15;
+
+ /* assign different values to mybox2's
+ instance variables */
+ mybox2.width = 3;
+ mybox2.height = 6;
+ mybox2.depth = 9;
+
+ // compute volume of first box
+ vol = mybox1.width * mybox1.height * mybox1.depth;
+ System.out.println("Volume is " + vol);
+
+ // compute volume of second box
+ vol = mybox2.width * mybox2.height * mybox2.depth;
+ System.out.println("Volume is " + vol);
+ }
+ }


خروجي توليد شده توسط اين برنامه بقرار زير مي باشد :

Volume is 3000
Volume is 162


بخوبي مشاهده مي كنيد كه داده مربوط به mybox1 كاملا" از داده موجود در

Nesta
01-07-2005, 07:32
اعلان نمودن اشيائ

بدست آوردن اشيائ از يك كلاس ، نوعي پردازش دو مرحله اي است . اول ، بايد يك
متغير از نوع همان كلاس اعلان نماييد . اين متغير يك شي ئ را تعريف نمي كند . در
عوض ، متغيري است كه مي تواند به يك شي ئ ارجاع نمايد. دوم ، بايد يك كپي فيزيكي
و واقعي از شي ئ بدست آورده و به آن متغير منتسب كنيد . مي توانيد اينكار را با
استفاده از عملگر new انجام دهيد . عملگر new بطور پويا ( يعني در حين اجرا )
حافظه را براي يك شي ئ تخصيص داده و يك ارجاع به آن را برمي گرداند .
اين ارجاع (reference) كمابيش آدرس آن شي ئ در حافظه است كه توسط new تخصيص
يافته است . سپس اين ارجاع در متغير ذخيره مي شود. بدين ترتيب ، در جاوا، كليه
اشيائ كلاس دار بايد بصورت پويا تخصيص يابند. اجازه دهيد كه به جزئيات اين روال
دقت نماييم .
در مثال قبلي ، يك خط مشابه خط زير براي اعلان يك شي ئ ازنوع Box استفاده شده

+ Box mybox = new Box)(;


اين دستور دو مرحله گفته شده را با يكديگر تركيب نموده است . براي اينكه هر
يك از مراحل را روشن تر درك كنيد، ميتوان آن دستور را بصورت زير بازنويسي نمود:


+ Box mybox; // declare reference to object
+ mybox = new Box)(; // allocate a Box object


خط اول ، myBox را بعنوان يك ارجاع به شيئي از نوع Box اعلان مي كند . پس از
اجراي اين خط ، mybox محتوي تهي (null) خواهد داشت كه نشانگر آن است كه هنوز
شي ئ بطور واقعي بوجود نيامده است . هر تلاشي براي استفاده ازmybox در اين مرحله
سبب بروز خطاي زمان كامپايل (compile-time error) خواهد شد . خط بعدي يك شي ئ
واقعي را تخصيص داده و يك ارجاع از آن به mybox انجام مي دهد . پس از اجراي خط
دوم ، مي توانيد از mybox بعنوان يك شي ئ Box استفاده نماييد . اما در واقعيت mybox
خيلي ساده آدرس حافظه شي ئ واقعي Box را نگهداري مي كند . تاثير اين دو
خط كد را در شكل زير نشان داده ايم .
نكته : كساني كه با C++/C آشنايي دارند احتمالا" توجه نموده اند كه ارجاعات شي ئ
مشابه اشاره گرها هستند . اين تشابه تا حدود زيادي صحيح است . يك ارجاع
شي ئ (object reference) مشابه يك اشاره گر حافظه است . مهمترين تفاوت
و كليد ايمني در جاوا اين است كه نمي توانيد از ارجاعات همچون
اشاره گرهاي واقعي استفاده نماييد . بدين ترتيب ، نمي توانيد ارجاع شي ئ
را بعنوان اشاره اي به موقعيت دلخواه حافظه يا بعنوان يك عدد صحيح بكار
بريد .

Statement Effect


Box mybox; | null |

mybox

|
| Width > | ;()mybox = new Box
mybox | Height |

| Depth |

Box object



نگاهي دقيقتر به new
شكل عمومي عملگر new بقرار زير مي باشد :

class-var = new classname)(;


در اينجا class-var يك متغير از نوع كلاسي است كه ايجاد كرده ايم . class name
نام كلاسي است كه مي خواهيم معرفي كنيم . نام كلاس كه بعد از آن پرانتزها قرار
گرفته اند مشخص كننده سازنده (constructor) كلاس است . سازنده تعريف مي كند كه
وقتي يك شي ئ از يك كلاس ايجاد شود ، چه اتفاقي خواهد افتاد . سازنده ها بخش مهمي
از همه كلاسها بوده و خصلتهاي بسيار قابل توجهي دارند .
بسياري از كلاسهاي دنياي واقعي (real-world) بطور صريحي سازندگان خود را
داخل تعريف كلاس ، معرفي مي كنند . اما اگر سازنده صريحي مشخص نشده باشد ، جاوا
بطور خودكار يك سازنده پيش فرض را عرضه مي كند . درست مثل حالت Box .
در اين مرحله ، ممكن است تعجب كنيد كه چرا از new براي مواردي نظير اعداد
صحيح و كاراكترها استفاده نمي شود. جواب اين است كه انواع ساده در جاوا بعنوان
اشيائ پياده سازي نمي شوند . در عوض ، آنها بعنوان متغيرهاي عادي پياده سازي
مي شوند. اينكار براي افزايش كارايي انجام مي گيرد. جاوا قادراست بدون استفاده
از رفتارهاي خاص نسبت به اشيائ، اين انواع ساده را بطور موثري پياده سازي كند.
نكته مهم اين است كه new حافظه را براي يك شي ئ طي زمان اجرا تخصيص مي دهد .
مزيت اين روش آن است كه برنامه شما ميتواند اشيائ مورد نيازش را طي زمان اجراي
برنامه ايجاد كند . اما از آنجاييكه محدوديت حافظه وجود دارد ، ممكن است new
بعلت عدم كفايت حافظه نتواند حافظه را به يك شي ئ تخصيص دهد . اگر چنين حالتي
پيش بيايد، يك استثنائ حين اجرا واقع خواهد شد. ولي در زبانهاي C++/C در صورت
عدم موفقيت ، مقدار تهي (null) برگردان مي شود .
اجازه دهيد يكبار ديگر تفاوت بين يك كلاس و يك شي ئ را مرور كنيم . يك كلاس
يك نوع جديد داده را ايجاد مي كند كه مي توان براي توليد اشيائ از آن نوع
استفاده نمود. يعني يك كلاس يك چهارچوب منطقي ايجاد مي كند كه ارتباط بين اعضائ
را توصيف مي نمايد . هنگاميكه يك شي ئ از يك كلاس را اعلان مي كنيد ، در حقيقت
نمونه اي از آن كلاس را بوجود آورده ايد. بدين ترتيب ، كلاس يك ساختار منطقي است .
يك شي داراي واقعيت فيزيكي است . ( يعني يك شي ئ فضايي از حافظه را اشغال در ذهن داشته باشيد .

Nesta
01-07-2005, 07:33
انتساب متغيرهاي ارجاع شي ئ

هنگامي كه يك انتساب انجام مي گيرد ، متغيرهاي ارجاع شي ئ رفتاري متفاوت با
آنچه در ذهن داريد ، بروز مي دهند . بعنوان مثال ، حدس مي زنيد كه قطعه زير
چكاري را انجام مي دهد ?

+ Box b1 = new Box)(;
+ Box b2 = b1;


ممكن است فكر كنيد كه يك كپي از شيئي كه b1 به آن انتساب شده به b2 منتسب
شده است . يعني ممكن است تصور كنيد كه b1و b2و به اشيائ جداگانه و متفاوتي
ارجاع مي كنند . اما ، اين تصور اشتباه است . در عوض ، پس از اجراي اين قطعه
هم b1 و هم b2 هر دو به يك شي ئ ارجاع مي كنند . انتساب b1و b2و هيچ حافظه اي را
تخصيص نداده و يا بخشي از يك شي ئ اصلي را كپي نمي كند . اين برنامه خيلي ساده b2
را به همان شيئي كه b1 به آن ارجاع مي كند ، ارجاع مي دهد . بدين ترتيب هر
تغيير ايجاد شده به شيئي از طريق b2 روي شي ئ كه b1 به آن ارجاع مي كند تاثير
مي گذارد چون هر دو شي ئ يكسان هستند .
اين حالت را در شكل زير بتصوير كشيده ايم :




| |
| Width |
> b1 | Height | Box object

> |
| Depth |
|


اگرچه b1و b2و هر دو به يك شي ئ ارجاع مي كنند ، اما بطريق ديگري با يكديگر
پيوند ندارند. بعنوان مثال ، يك شي ئ پس آيند ( متعاقب ) به b1 خيلي ساده b1 را
از شي ئ اوليه جدا كرده (un hook) بدون اينكه تاثيري روي شي ئ اوليه يا b2 داشته
باشد . بعنوان مثال :

+ Box b1 = new Box)(;
+ Box b2 = b1;
+ //...
+ b1 = null;


در اينجا b1 برابر تهي (null) شده ، اما b2 همچنان به شي ئاوليه ارجاع ميكند.
يادآوري : هنگاميكه يك متغير ارجاع شي ئ را به متغير ارجاع شي ئ ديگري انتساب
مي دهيد ، يك كپي از شي ئ بوجود نيامده بلكه فقط يك كپي از ارجاع

Nesta
01-07-2005, 07:34
چرا جاوا براي اينترنت اهميت دارد

اينترنت جاوا را پيشاپيش زبانهاي برنامه نويسي قرار داد و در عوض جاوا
تاثيرات پيش برنده اي روي اينترنت داشته است . دليل اين امر بسيار ساده است :
جاوا سبب گسترش فضاي حركت اشيائ بطور آزادانه در فضاي الكترونيكي مي شود . در
يك شبكه ، دو نوع طبقه بندي وسيع از اشيائ در حال انتقال بين سرويس دهنده و
رايانه شخصي شما وجود دارد : اطلاعات غير فعال (passive) و برنامه هاي فعال
(active) و پويا (dynamic) . بعنوان نمونه هنگاميكه پست الكترونيكي e-mail خود
را مرور مي كنيد ، در حال بررسي داده هاي غير فعال هستيد . حتي هنگاميكه يك
برنامه را گرفته و بار گذاري مي كنيد ، ماداميكه از آن برنامه استفاده نكنيد
كدهاي برنامه بعنوان داده هاي غير فعال هستند . اما نوع دوم اشيائي كه امكان
انتقال به رايانه شخصي شما را دارند ، برنامه هاي پويا و خود اجرا هستند . چنين
برنامه اي اگر چه توسط سرويس دهنده ارائه و انتقال مي يابد ، اما يك عامل فعال
روي رايانه سرويس گيرنده است . بعنوان نمونه سرويس دهنده قادر است برنامه اي را
بوجود آورد كه اطلاعات و داده هاي ارسالي توسط سرويس دهنده را نمايش دهد .
بهمان اندازه كه برنامه هاي پويا و شبكه اي شده موردتوجه قرار گرفته اند بهمان
نسبت نيز دچار مشكلاتي در زمينه امنيت و قابليت حمل هستند . قبل از جاوا ، فضاي
الكترونيكي شامل فقط نيمي از وروديهايي بود كه اكنون وجود دارند . همانطوريكه
خواهيد ديد ، جاوا درها را براي يك شكل جديد از برنامه ها باز نموده است :
ريز برنامه ها (applets) .

ريز برنامه ها و برنامه هاي كاربردي جاوا
از جاوا براي توليد دو نوع برنامه مي توان استفاده نمود: برنامه هاي كاربردي
(applications) و ريز برنامه ها (applets) . يك برنامه كاربردي برنامه اي است كه
روي رايانه شما و تحت نظارت يك سيستم عامل اجرا مي شود . بدين ترتيب يك برنامه
كاربردي ايجاد شده توسط جاوا مشابه برنامه هاي ايجاد شده توسط Cو C++و خواهد
بود. هنگاميكه از جاوا براي توليد برنامه هاي كاربردي استفاده ميكنيم ، تفاوتهاي
زيادي بين اين زبان و ساير زبانهاي برنامه نويسي مشاهده نمي كنيم . اما ويژگي
جاوا براي توليد ريز برنامه ها داراي اهميت زيادي است . يك ريز برنامه (applet)
يك برنامه كاربردي است كه براي انتقال و حركت روي اينترنت و اجرا توسط يك
مرورگر قابل انطباق با جاوا طراحي شده است . يك ريز برنامه در حقيقت يك برنامه
ظريف جاوا است كه بطور پويا در سراسر اينترنت قابل بارگذاري باشد ، درست مثل
يك تصوير، يك فايل صوتي يا يك قطعه ويدئويي .تفاوت اصلي در اينست كه ريزبرنامه
يك برنامه كاربردي هوشمند است و شباهتي با يك تصوير متحرك يا فايل رسانه اي
ندارد . بعبارت ديگر اين برنامه قادر به عكس العمل در برابر ورودي كاربر و
ايجاد تغييرات پويا است .
ريز برنامه هاي جاوا بسيار جالب و هيجان انگيزند و قادرند دو مشكل اصلي يعني
امنيت و قابليت حمل را پشت سر بگذارند . قبل از ادامه بحث بهتر است مفهوم اصلي
اين دو مشكل را بيشتر مورد بررسي قرار دهيم .

امنيت
همانطوريكه خودتان هشيار هستيد ، هرگاه كه يك برنامه عادي (normal) را بار
گذاري مي كنيد با خطر يك حمله ويروسي مواجه خواهيد شد . قبل از جاوا اكثر
كاربران ، برنامه هاي قابل اجرا را بتناوب گرفته و بارگذاري مي كردند و قبل از
اجرا براي ويروس زدايي اقدام به اسكن (Scanning) برنامه ها مي كردند . با اين
حال بسياري از اين كاربران نسبت به حمله ويروسها به سيستم خود نگران بودند .
علاوه بر ويروسها ، نوع ديگري از برنامه هاي مزاحم وجود دارند كه بايد در
برابر آنها نيز ايمن ماند . اين نوع برنامه ها قادرند اطلاعات خصوصي نظير شماره
كارتهاي اعتباري ،ترازهاي حساب بانكي و كلمات عبور براي جستجو درسيستم فايلهاي
محلي رايانه شما را كشف نموده و استفاده نمايند . جاوا توسط ايجاد يك ديواره
آتش (firewall) بين رايانه شما و برنامه شبكه اي شده ، بر اين مشكلات فائق آمده
است .
هنگاميكه از يك مرورگر قابل انطباق با جاوا در وب استفاده ميكنيد، ميتوانيد
با اطمينان ريزبرنامه هاي جاوا را بارگذاري نماييد، بدون اينكه از حمله ويروسها
و برنامه هاي مزاحم واهمه اي داشته باشيد . جاوا يك برنامه خاص جاوا را به محيط
خاص اجرايي مربوطه اش منحصر كرده و اجازه دسترسي اين برنامه به ساير بخشهاي
رايانه را نمي دهد و بدين ترتيب مشكل امنيت را حل كرده است . توانايي بارگذاري
ريز برنامه ها بصورت مطمئن يكي از مهمترين جنبه هاي جاوا است .

قابليت حمل
انواع مختلفي از رايانه ها و سيستم هاي عامل در سراسر دنيا مورد استفاده قرار
مي گيرند و بسياري ازاين سيستم ها با اينترنت متصل ميشوند. براي اينكه برنامه ها
بتوانند بطور پويا روي انواع مختلف سيستم ها و محيط هاي عامل متصل به اينترنت
بارگذاري شوند ، وسائلي براي توليد كدهاي اجرايي و قابل حمل مورد نياز است .
همانطوريكه بزودي خواهيد ديد ، همان مكانيسمي كه امنيت را بوجود مي آورد سبب
ايجاد قابليت حمل نيز خواهد شد . در حقيقت راه حل جاوا براي اين مسائل هم زيبا

مهمان
01-07-2005, 07:34
سلام نستا جان ممنون از مقاله ها
اگر امکان داره مطلب درباره J2ME هم اگر داريد بگذاريد.
با تشکر از زحمات شما

Nesta
01-07-2005, 07:35
معرفي روشها

موضوع روشها بسيار گسترده است ، چون جاوا قدرت و انعطاف پذيري زيادي به
روشها داده است .
شكل عمومي يك روش بقرار زير است :

type name(parameter-list ){
// body of method
}


در اينجا ، type مشخص كننده نوع داده برگشت شده توسط روش است . اين نوع هر
گونه نوع معتبر شامل نوع كلاسي كه ايجاد كرده ايد ، مي تواند باشد . اگر روش
مقداري را برنمي گرداند ، نوع برگشتي آن بايد Void باشد . نام روش توسط name
مشخص مي شود . اين نام مي تواند هر نوع شناسه مجاز باشد ، البته غير از آنهايي
كه قبلا" براي اقلام داخل قلمرو جاري استفاده شده باشند . parameter-list يك
پس آيند نوع و شناسه است كه توسط يك كاما جدا مي شود . پارامترها ضرورتا"
متغيرهايي هستند كه مقدار آرگومان (arguments) گذركرده در روش ، هنگام فراخواني
را جذب مي كنند . اگر روش فاقد پارامتر باشد ، آنگاه فهرست پارامتر تهي خواهد
بود .
روشهايي كه بجاي void يك نوع برگشتي (return) دارند ، مقداري را به روال
فراخواننده با استفاده از شكل بعدي دستور return باز مي گردانند .

return value;


در اينجا value همان مقدار برگشتي است .

افزودن يك روش به كلاس Box
اگرچه خيلي خوب است كه كلاسي ايجاد نماييم كه فقط شامل داده باشد، اما بندرت
چنين حالتي پيش مي آيد. در اغلب اوقات از روشها براي دسترسي به متغيرهاي نمونه
تعريف شده توسط كلاس ، استفاده مي كنيم . در حقيقت ، روشها توصيف گر رابط به
اكثر كلاسها هستند . اين امر به پياده سازان كلاس امكان مي دهد تا صفحه بندي
مشخصي از ساختارهاي داده داخلي را در پشت تجريدهاي (abstractions) روشهاي
زيباتر پنهان سازند . علاوه بر تعريف روشهايي كه دسترسي به داده ها را بوجود
مي آورند ، مي توانيد روشهايي را تعريف كنيد كه بصورت داخلي و توسط خود كلاس
مورد استفاده قرار مي گيرند .
اجازه دهيد با اضافه كردن يك روش به كلاس Box شروع كنيم . ممكن است درمثالهاي
قبلي شما هم احساس كرده باشيد كه محاسبه فضاي اشغالي (Volume) يك box چيزي
است كه توسط كلاس Box در مقايسه با كلاس BoxDemo بسيار راحت تر مديريت مي شود .
بعلاوه ، چون فضاي اشغالي يك box بستگي به اندازه آن دارد، بنظر مي رسد كه بهتر
است كلاس Box اين محاسبه را انجام دهد . براي انجام اينكار، بايد بصورت زير يك
روش را به Box اضافه نماييد :

+ // This program includes a method inside the box class.
+
+ class Box {
+ double width;
+ double height;
+ double depth;
+
+ // display volume of a box
+ void volume )({
+ System.out.print("Volume is ");
+ System.out.println(width * height * depth);
+ }
+ }
+
+ class BoxDemo3 {
+ public static void main(String args[] ){
+ Box mybox1 = new Box)(;
+ Box mybox2 = new Box)(;
+
+ // assign values to mybox1's instance variables
+ mybox1.width = 10;
+ mybox1.height = 20;
+ mybox1.depth = 15;
+
+ /* assign different values to mybox2's
+ instance variables */
+ mybox2.width = 3;
+ mybox2.height = 6;
+ mybox2.depth = 9;
+
+ // display volume of first box
+ mybox1.volume)(;
+
+ // display volume of second box
+ mybox2.volume)(;
+ }
+ }


اين برنامه خروجي زير را توليد مي كند كه مطابق خروجي روايت قبلي همين
برنامه است . Volume is 3000
Volume is 162

با دقت به دو خط بعدي كدها نگاه كنيد :

+ mybox1.volume)(;
+ mybox2.volume)(;


خط اول در اينجا ، روش ()volume را روي mybox1 قرار مي دهد. يعني كه اين خط
()volume را با استفاده از نام شي ئ كه بدنبال آن عملگر نقطه اي قرار گرفته است
نسبت به شي ئ mybox1 فراخواني مي كند . بدين ترتيب ، فراخواني ()mybox1.volume
فضاي اشغالي boxتوصيف شده بوسيله mybox1را نمايش داده و فراخواني ()mybox2.volume
فضاي اشغالي box توصيف شده بوسيله mybox2 را نمايش مي دهد. هر بار كه ()volume
خواسته شود ، فضاي اشغالي يك box مشخص را نمايش خواهد داد .
اگر با مفهوم فراخواني يك روش نا آشنا هستيد ، توصيف بعدي موضوع را تا حد
زيادي روشن مي كند . هنگاميكه ()mybox1.volume اجرا شود، سيستم حسن اجراي جاوا
كنترل را به كدي كه داخل ()volume تعريف شده منتقل مي كند . پس از اينكه دستور
داخل ()volume اجرا شود ، كنترل به روال فراخواننده برگشته و اجراي خط كد بعد
از فراخواني از سر گرفته خواهد شد . از يك نقطه نظر عمومي ، يك روش (method)
شيوه جاوا براي پياده سازي زير روالهاست (subroutions) .
يك نكته مهم درون روش ()volume وجود دارد : ارجاع به متغيرهاي نمونه width height
و depthو بصورت مستقيم بدون يك نام شي ئ يا يك عملگر نقطه اي پيش آيند
( قبلي ) انجام مي گيرد. وقتي يك روش از متغير نمونه اي كه توسط كلاس خود تعريف
شده استفاده مي كند ، اينكار را بطور مستقيم و بدون ارجاع صريح به يك شي ئ و
بدون استفاده از عملگر نقطه اي انجام مي دهد . اگر درباره آن بينديشيد ، بخوبي
درك مي كنيد . يك روش همواره نسبت به شي ئ از كلاس خود قرار داده مي شود . وقتي
اين تعبيه اتفاق مي افتد ، شي ئ شناخته شده است . بدين ترتيب ، داخل يك روش
نيازي به مشخص كردن يك شي ئ براي بار دوم وجود ندارد . اين بدان معني است كه width
، height،و depthو داخل ()volume بطور صريحي به كپيهاي متغيرهاي پيدا شده
در آن شي ئ كه ()volume را فعال مي كند ، ارجاع مي كنند .
اجازه دهيد مجددا" مرور كنيم : وقتي يك متغير نمونه بوسيله كدي كه بخشي از
كلاسي كه آن متغير نمونه در آن تعريف شده نيست مورد دسترسي قرار مي گيرد
اينكار بايد از طريق يك شي ئ با استفاده از عملگر نقطه اي انجام شود. اما ، وقتي
كه متغير نمونه بوسيله كدي كه بخشي از همان كلاس مربوط به آن متغير نمونه
باشد مورد دسترسي قرار گيرد ، به آن متغير مي توان بطور مستقيم ارجاع نمود .
همين مورد براي بررسي روشها نيز پياده سازي مي شود .

برگرداندن يك مقدار
در حاليكه پياده سازي ()volume محاسبه فضاي اشغالي يك box داخل كلاس مربوطه Box
را حركت مي دهد ، اما بهترين راه نيست . بعنوان مثال ، اگر بخش ديگري از
برنامه شما بخواهد فضاي اشغالي يك box را بداند ، اما مقدار آن را نمايش ندهد
چكار بايد كرد ? يك راه بهتر براي پياده سازي ()volume اين است كه آن را وادار
كنيم تا فضاي اشغالي box را محاسبه نموده و نتيجه را به فراخواننده (caller)
برگرداند . مثال بعدي كه روايت پيشرفته تر برنامه قبلي است ، همين كار را انجام
مي دهد :

+ // Now/ volume )(returns the volume of a box.
+
+ class Box {
+ double width;
+ double height;
+ double depth;
+
+ // compute and return volume
+ doble volume )({
+ return width * height * depth;
+ }
+ }
+
+ class BoxDemo4 {
+ public static void main(String args[] ){
+ Box mybox1 = new Box)(;
+ Box mybox2 = new Box)(;
+ double vol;
+
+ // assign values to mybox1's instance variables
+ mybox1.width = 10;
+ mybox1.height = 20;
+ mybox1.depth = 15;
+
+ /* assign different values to mybox2's
+ instance variables */
+ mybox2.width = 3;
+ mybox2.height = 6;
+ mybox2.depth = 9;
+
+ // get volume of first box
+ vol = mybox1.volume)(;
+ System.out.println("Volume is " + vol);
+
+ // get volume of second box
+ vol = mybox2.volume)(;
+ System.out.println("Volume is " + vol);
+ }
+ }


همانطوريكه مي بينيد ، وقتي ()volume فراخواني مي شود ، در سمت راست يك
دستور انتساب قرار مي گيرد. در سمت چپ يك متغير است كه در اين حالت vol ميباشد
كه مقدار برگشتي توسط ()volume را دريافت مي كند . بدين ترتيب ، بعد از اجراي + vol = mybox.volume)(;

مقدار ()mybox1.volume برابر 3000 شده و سپس اين مقدار در vol ذخيره خواهد
شد .
دو نكته مهم درباره برگرداندن مقادير وجود دارد :
ؤ نوع داده برگشت شده توسط يك روش بايد با نوع برگشتي مشخص شده توسط همان
روش سازگار باشد. بعنوان مثال ، اگر نوع برگشتي برخي روشها boolean باشد، نبايد
يك عدد صحيح را برگردان نماييد .
ؤ متغيري كه مقدار برگشتي توسط يك روش را دريافت مي كند ( نظير vol در اين
مثال ) بايد همچنين با نوع برگشتي مشخص شده براي آن روش سازگاري داشته باشد .
يك نكته ديگر : برنامه قبلي را مي توان كمي كاراتر نيز نوشت زيرا هيچ نياز
واقعي براي متغير vol وجود ندارد . فراخواني ()volume را مي شد بطور مستقيم
( بصورت زير ) در دستور ()println استفاده نمود :

+ System.out.println("Volume is " + mybox1.volume90);


در اين حالت ، هنگاميكه ()println اجرا مي شود ، ()mybox1.volume بصورت
خودكار فراخواني شده و مقدار آن به ()println گذر مي كند .

افزودن روشي كه پارامترها را مي گيرد
اگرچه برخي روشها نيازي به پارامترها ندارند ، اما اكثر روشها اين نياز را
دارند . پارامترها به يك روش ، امكان عمومي شدن را مي دهند . يعني كه يك روش
پارامتردار (parameterized) مي تواند روي طيف گوناگوني از داده ها عمل كرده و
يا در شرايط نسبتا" گوناگوني مورد استفاده قرار گيرد . براي مشاهده اين نكته
از يك برنامه خيلي ساده استفاده مي كنيم . در اينجا روشي را مشاهده مي كنيد كه
مربع عدد 10 را برمي گرداند :

+ int square)(
+ {
+ return 10 * 10;
+ }


در حاليكه اين روش در حقيقت مقدار مربع عدد 10 را برمي گرداند ، اما كاربرد
آن بسيار محدود است . اما اگر روش را بگونه اي تغيير دهيد كه پارامتري را بگيرد
همانطوريكه خواهيد ديد ، مي توانيد ()square را مفيدتر بسازيد .

+ int square(int i)
+ {
+ return i * i;
+ }


اكنون ()square مربع هر مقداري را كه فراخواني شود ، برمي گرداند . يعني كه
اكنون ()square يك روش با هدف عمومي است كه مي تواند مربع هر مقدار عدد صحيح
( بجاي فقط عدد 10 ) را محاسبه مي كند .
مثالي را در زير مشاهده مي كنيد :

+ int x/ y;
+ x = square(5); // x equals 25
+ x = square(9); // x equals 81
+ y = 2;
+ x = square(y); // x equals 4


در اولين فراخواني ()square مقدار 5 به پاارمتر i گذر مي كند . در دومين
فراخواني ، i مقدار 9 را دريافت مي كند . سومين فراخواني مقدار y كه در اين
مثال 2 است را مي گذراند . همانطوريكه اين مثالها نشان مي دهند، ()square قادر
است مربع هر داده اي را كه از آن مي گذرد ، برگرداند .
مهم است كه دو اصطلاح پارامتر (parameter) و آرگومان (argument) را بوضوح
درك نماييم . پارامتر ، متغيري است كه توسط يك روش تعريف شده و هنگام فراخواني
روش ، مقداري را دريافت مي كند. بعنوان مثال ، در ()square، i يك پارامتر است .
آرگومان مقداري است كه هنگام فراخواني يك روش به آن گذر مي كند . بعنوان مثال
(َ100)square مقدار100 را بعنوان يك آرگومان گذر ميدهد. داخل ()square، پارامتر i
مقداري را دريافت مي كند .
مي توانيد يك روش پارامتردار را براي توسعه كلاس Box مورداستفاده قرار دهيد.
در مثالهاي قبلي ، ابعاد هر يك box بايد بصورت جداگانه با استفاده از يك سلسله
دستورات نظير مورد زير ، تعيين مي شدند :

+ mybox1.width = 10;
+ mybox1.height = 20;
+ mybox1.depth = 15;


اگرچه اين كد كاري مي كند، اما بدو دليل داراي اشكال است . اول اينكه ، اين
كد بد تركيب و مستعد خطا است . بعنوان مثال ، خيلي ساده امكان دارد تعيين يك
بعد فراموش شود . دوم اينكه در برنامه هاي خوب طراحي شده جاوا ، متغيرهاي نمونه
فقط از طريق روشهاي تعريف شده توسط كلاس خودشان قابل دسترسي هستند . در آينده
قادر خواهيد بود تا رفتار يك روش را تغيير دهيد ، اما نمي توانيد رفتار يك
متغير نمونه بي حفاظ ( افشا شده ) را تغيير دهيد .
بنابراين ، يك راه بهتر براي تعيين ابعاد يك box اين است كه يك روش ايجاد
نماييم كه ابعادbox را در پارامترهاي خود نگهداشته و هر متغير نمونه را بصورت
مناسبي تعيين نمايد . اين برنامه توسط برنامه زير ، پياده سازي خواهد شد :

+ // This program uses a parameterized method.
+
+ class Box {
+ double width;
+ double height;
+ double depth;
+
+ // compute and return volume
+ double volume )({
+ return width * height * depth;
+ }
+ // sets dimensions of box
+ void setDim(double w/ double h/ double d ){
+ width = w;
+ height = h;
+ depth = d;
+ }
+ }
+
+ class BoxDemo5 {
+ public static void main(String args[] ){
+ Box mybox1 = new Box)(;
+ Box mybox2 = new Box)(;
+ double vol;
+
+ // initialize each box
+ mybox.setDim(10/ 20/ 15);
+ mybox.setDim(3/ 6/ 9);
+
+ // get volume of first box
+ vol = mybox1.volume)(;
+ System.out.println("Volume is " + vol);
+
+ // get volume of second box
+ vol = mybox2.volume)(;
+ System.out.println("Volume is " + vol);
+ }
+ }


همانطوريكه مي بينيد ، روش ()setDim براي تعيين ابعاد هر box مورد استفاده
قرار مي گيرد . بعنوان مثال وقتي

+ mybox1.setDim(10/ 20/ 15);


اجرا مي شود ، عدد 10 به پارامتر w ، 20به h و 15به d كپي مي شود . آنگاه heightو depthو نسبت داده

Nesta
01-07-2005, 07:37
سلام نستا جان
پس بقيه مطلب چي شد!!! :)
سلام آقا اینا رو فعلا داشته باش .بخون تا بدا باز بگذارم این دیگه از پایه هست.

Nesta
01-07-2005, 07:41
سازندگان Constructors

خيلي خسته كننده است كه هربار يك نمونه ايجاد مي شود كليه متغيرهاي يك كلاس
را مقداردهي اوليه نماييم . حتي هنگاميكه توابع سهل الاستفاده نظير ()setDim را
اضافه مي كنيد ، بسيار ساده تر و دقيق تر آن است كه كليه تنظيمات در زمان ايجاد
اوليه شي ئ انجام شود . چون نياز به مقدار دهي اوليه بسيار رايج است ، جاوا به
اشيائ امكان مي دهد تا در زمان ايجاد شدن خودشان را مقدار دهي اوليه نمايند .
اين مقدار دهي اوليه خودكار بااستفاده از سازنده (constructor) انجام مي گيرد.
يك سازنده بمحض ايجاد يك شي ئ بلافاصله آن را مقدار دهي اوليه مي نمايد . اين
سازنده نام همان كلاسي را كه در آن قرار گرفته اختيار نموده و از نظر صرف و نحو
مشابه يك روش است . وقتي يكبار سازنده اي را تعريف نماييد، بطور خودكار بلافاصله
پس از ايجاد يك شي ئ و قبل از اينكه عملگر new تكميل شود ، فراخواني خواهد شد .
سازندگان كمي بنظر عجيب مي آيند زيرا فاقد نوع برگشتي و حتي فاقد void هستند .
بخاطر اينكه نوع مجازي برگشتي سازنده يك كلاس ، همان نوع خود كلاس مي باشد . اين
وظيفه سازنده است كه وضعيت داخلي يك شي ئ را بگونه اي مقدار دهي اوليه نمايد كه
كدي كه يك نمونه را ايجاد مي كند ، بلافاصله يك شي ئ كاملا" قابل استفاده و مقدار
دهي شده بوجود آورد .
مي توانيد مثال مربوط به Box را طوري بازنويسي كنيد كه ابعاد يك box وقتي
كه يك شي ئ ساخته مي شود ، بطور خودكار مقدار دهي اوليه شوند . براي انجام اين
كار ، يك سازنده را جايگزين ()setDim نماييد . كار را با تعريف يك سازنده ساده
شروع مي كنيم كه بسادگي ابعاد هر box را بهمان مقادير تنظيم ميكند. اين روايت
جديد بقرار زير است :

+ /* Here/ Box uses a constructor to initialize the
+ dimensions of a box.
+ */
+ class Box {
+ double width;
+ double height;
+ double depth;
+
+ // This is the constructor for Box.
+ Box )({
+ System.out.println("Constructing Box");
+ width = 10;
+ height = 10;
+ depth = 10;
+ }
+
+ // compute and return volume
+ double volume )({
+ return width * height * depth;
+ }
+ }
+
+ class BoxDemo6 {
+ public static void main(String args[] ){
+ // declare/ allocate/ and initialize Box objects
+ Box mybox1 = new Box)(;
+ Box mybox2 = new Box)(;
+
+ double vol;
+
+ // get volume of first box
+ vol = mybox1.volume)(;
+ System.out.println("volume is " + vol);
+
+ // get volume of second box
+ vol = mybox2.volume)(;
+ System.out.println("volume is " + vol);
+ }
+ }


پس از اجراي اين برنامه ، خروجي آن بصورت زير خواهد شد :

Constructing Box
Constructing Box
Volume is 1000
Volume is 1000


همانطوريكه مشاهده مي كنيد ، mybox1و mybox2و هنگام ايجاد شدن بوسيله ()Box
مقداردهي اوليه ميشوند. چون سازنده به همه boxها همان ابعاد يعني 10x10x10
را مي دهد ، هم mybox1 و هم mybox2 فضاي اشغالي يكساني خواهند داشت . دستور
()println داخل ()Box فقط بمنظور توصيف بهتر قرار گرفته است . اكثر توابع
سازنده چيزي را نمايش نمي دهند. آنها فقط خيلي ساده ، اشيائ را مقدار دهي اوليه
مي كنند .
قبل از ادامه بحث ، عملگر new را مجددا" بررسي ميكنيم . همانطوريكه مي دانيد
هنگاميكه يك شي ئ را اختصاص مي دهيد ، شكل عمومي زير را مشاهده مي كنيد :

class-var = new classname)(;


اكنون مي توانيد بفهميد چرا پرانتزها بعد از نام كلاس مورد نيازند . آنچه
واقعا" اتفاق مي افتد اين است كه سازنده كلاس فراخواني شده است . بدين ترتيب
در خط

+ Box mybox1 = new Box)(;


()newBox سازنده ()Box را فراخواني مي كند اگر يك سازنده براي كلاس تعريف
نشود ، آنگاه جاوا يك سازنده پيش فرض براي كلاس ايجاد مي كند . بهمين دليل خط
قبلي از كد در روايتهاي اوليه Box كه هنوز يك سازنده تعريف نشده بود ، كار
مي كرد. سازنده پيش فرض بطور خودكار كليه متغيرهاي نمونه را با عدد صفر، مقدار
دهي اوليه مي نمايد . سازنده پيش فرض غالبا" براي كلاسهاي ساده كفايت مي كند
اما براي كلاسهاي پيچيده تر كفايت نمي كند . هر بار كه سازنده خاص خود را تعريف
كنيد ، ديگر سازنده پيش فرض استفاده نخواهد شد .

سازندگان پارامتردار شده (parameterized)
هنگاميكه سازنده ()Box در مثال قبلي يك شي ئ Box را مقدار دهي اوليه مي كند
چندان سودمند نيست ، زيرا كليه box ها ، ابعاد يكساني دارند . آنچه مورد نياز
است ، روشي براي ساخت اشيائ Box داراي ابعاد گوناگون است . ساده ترين راه
افزودن پارامترها به سازنده است . همانطوريكه احتمالا" حدس مي زنيد ، اين عمل
سودمندي سازندگان را افزايش مي دهد . بعنوان مثال ، روايت بعدي Box يك سازنده
پارامتردار شده را تعريف مي كند كه ابعاد يك box را همانطوريكه آن پارامترها
مشخص شده اند ، تنظيم مي كند. دقت كافي به چگونگي ايجاد اشيائ Box داشته باشيد.

+ /* Here/ Box uses a parameterized constructor to
+ initialize the dimensions of a box.
+ */
+ class Box {
+ double width;
+ double height;
+ double depth;
+
+ // This is the constructor for Box.
+ Box(double w/ double h/ double d ){
+ width = w;
+ height = h;
+ depth = d;
+ }
+
+ // compute and return volume
+ double volume )({
+ return width * height * depth;
+ }
+ }
+
+ class BoxDemo7 {
+ public static void main(String args[] ){
+ // declare/ allocate/ and initialize Box objects
+ Box mybox1 = new Box(10/ 20/ 15);
+ Box mybox2 = new Box(3/ 6/ 9);
+
+ double vol;
+
+ // get volume of first box
+ vol = mybox1.volume)(;
+ System.out.println("volume is " + vol);
+
+ // get volume of second box
+ vol = mybox2.volume)(;
+ System.out.println("volume is " + vol);
+ }
+ }


خروجي اين برنامه بقرار زير است :

Volume is 3000
Volume is 162


همانطوريكه مي بينيد ، هر شي ئ همانطوريكه در پارامترهاي سازنده اش مشخص شده
مقدار دهي اوليه خواهد شد .

+ Box mybox1 = new Box(10/ 20/ 15);


هنگاميكه new شي ئ را ايجاد مي كند ، مقادير 10 ، 20 ، 15 به سازنده ()Box
گذر مي كنند . بدين ترتيب كپي خاص mybox1از widthز، height،و depthو بترتيب

Nesta
01-07-2005, 07:41
واژه كليدي This

گاهي لازم است يك روش به شي ئ كه آن را فراخواني نموده ، ارجاع نمايد . براي
اين منظور، جاوا واژه كليدي this را تعريف كرده است . this را مي توان داخل هر
روشي براي ارجاع به شي ئ جاري (current) استفاده نمود. يعني this همواره ارجاعي
است به شي ئ كه روش روي آن فراخواني شده است . مي توانيد از this هر جايي كه
ارجاع به يك شي ئ از نوع كلاس جاري مجاز باشد ، استفاده نماييد .
براي اينكه بفهميد this به چه چيزي ارجاع مي كند ، روايت بعدي ()Box را در
نظر بگيريد :

+ // A redundant use of this.
+ Box(double w/ double h/ double d ){
+ this.width = w;
+ this.height = h;
+ this.depth = d;
+ }


اين روايت ()Box دقيقا" مثل روايت اوليه كار مي كند . استفاده از this به
ندرت انجام گرفته اما كاملا"صحت دارد. داخل ()Box همواره this به شي ئ فراخوانده
شده ارجاع مي كند . اگرچه در اين مثالها بندرت پيش آمده مي كند . اگرچه در اين
مثالها بندرت پيش آمده ، اما this در ساير متون بسيار مفيد است .

مخفي نمودن متغير نمونه
حتما" مي دانيد كه اعلان دو متغير محلي با يك نام داخل يك قلمرو يا قلمروهاي
بسته شده ، غير مجاز است . بطرز خيلي جالبي ، مي توانيد متغيرهاي محلي شامل
پارامترهاي رسمي براي روشها ، داشته باشيد كه با اسامي متغيرهاي نمونه كلاسها
مشترك باشند . اما ، هنگاميكه يك متغير محلي همان اسم متغير نمونه را داشته
باشد، متغير محلي ، متغير نمونه را مخفي مي سازد. بهمين دليل بود كه از width height
و depthو بعنوان اسامي پارامترهاي سازنده ()Box داخل كلاس Box استفاده
نكرديم . اگر از آنها بهمين روش استفاده مي كرديم ، آنگاه width به پارامتر
رسمي ارجاع مي كرد و متغير نمونه width را مخفي مي ساخت . اگرچه آسان تر است
كه از اسامي متفاوت استفاده كنيم ، اما راه حل ديگري براي چنين شرايطي وجود
دارد . چون this امكان ارجاع مستقيم به شي ئ را به شما مي دهد ، مي توانيد با
استفاده از آن هر نوع تصادف و يكي شدن اسامي بين متغيرهاي نمونه و متغيرهاي
محلي را رفع نماييد . بعنوان مثال ، در اينجا روايت ديگري از ()Box وجود دارد
كه از width، height،و depthو بعنوان اسامي پارامترها استفاده نموده و آنگاه
از this براي دستيابي به متغيرهاي نمونه با همين اسامي استفاده كرده است :

+ // Use this to resolve name-space collisions.
+ Box(double width/ doublee height/ double depth ){
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
+ }


احتياط . استفاده از this درچنين متني ممكن است گاهي گيج كننده بشود و برخي
از برنامه نويسان مراقب هستند تا از اسامي متغيرهاي محلي و پارامترهاي رسمي كه
متغيرهاي نمونه را مخفي مي سازند ، استفاده نكنند. البته ، ساير برنامه نويسان
طور ديگري فكر ميكنند . يعني معتقدند استفاده از اسامي مشترك براي وضوح ، ايده
خوبي است و از this براي غلبه بر مخفي سازي متغير نمونه بهره ميگيرند. انتخاب
يكي از دو روش با سليقه شما ارتباط دارد .
اگرچه this در مثالهايي كه تاكنون نشان داده ايم ارزش زيادي نداشته ، اما در واهد بود .

Nesta
01-07-2005, 07:42
جمع آوري زباله Garbage collection

از آنجاييكه اشيائ بصورت پويا و با استفاده از عملگر new تخصيص مي يابند
ممكن است تعجب كنيد كه چگونه اين اشيائ خراب شده و حافظه آنها آزاد شده و
مجددا" تخصيص مي يابد . در برخي زبانها ، نظير C++ ، اشيائ تخصيص يافته پويا
بايد بصورت دستي و با استفاده از عملگر delete رها شوند . جاوا در اين مورد
روش متفاوتي دارد. جاوا اينكار را بصورت خودكار براي شما انجام مي دهد. تكنيكي
كه تخصيص مجدد اشيائرا انجام ميدهد،اصطلاحا" جمع آوري زباله garbage collection
ناميده مي شود. طرز كار آن بشرح بعدي مي باشد : وقتي كه هيچگونه ارجاعي به يك
شي ئ وجود نداشته باشد، فرض مي شود كه آن شي ئ نيازي به خراب كردن اشيائ بصراحت
نظير زبان C++ وجود ندارد . جمع آوري زباله طي اجراي برنامه شما فقط بصورت
پراكنده و گاه و بيگاه اتفاق مي افتد ( البته اصلا" اگر اتفاق بيفتد ) . اين
جريان بخاطر اينكه يك يا دو شي ئ وجود دارند كه ديگر استفاده نمي شوند ، اتفاق
نمي افتد . بعلاوه ، پياده سازيهاي گوناگون حين اجراي جاوا ، شيوه هاي متفاوتي
در جمع آوري زباله بوجود مي آورد، اما در غالب اوقات هنگام نوشتن برنامه هايتان اين موضوع نگراني نداشته باشيد .

Nesta
01-07-2005, 07:42
روش ()finalize

گاهي لازم است تا يك شي ئ هنگاميكه در حال خراب شدن است ، يك عمل خاصي را
انجام دهد. بعنوان مثال ، ممكن است يك شي ئ دربرگيرنده منابع غير جاوا نظير يك
دستگيره فايل (file handle) يا فونت كاراكتر ويندوز باشد، و مي خواهيد اطمينان
يابيد كه قبل از اينكه آن شي ئ خراب شود ، منابع فوق آزاد شوند . براي اداره
چنين شرايطي ، جاوا مكانيسمي تحت نام finalization ( تمام كننده ) فراهم آورده
است .
با استفاده از اين مكانيسم ، مي توانيد عمليات مشخصي را تعريف نماييد كه
زمانيكه يك شي ئ در شرف مرمت شدن توسط جمع آوري زباله است ، اتفاق بيفتند .
براي افزودن يك تمام كننده (finalizer) به يك كلاس ، خيلي راحت كافي است تا
روش ()finalize را تعريف نماييد. سيستم حين اجراي جاوا هرگاه در شرف چرخش مجدد
يك شي ئ از كلاسي باشد ، اين روش را فراخواني مي كند . داخل روش ()finalize شما
عملياتي را مشخص مي كنيد كه بايد درست قبل از خرابي آن شي ئ انجام گيرند . جمع
كننده زباله (garbage collector) بطور متناوب اجرا شده و بدنبال اشيايي ميگردد
كه ديگر مورد ارجاع هيچيك از شرايط اجرايي نبوده و يا غير مستقيم توسط ساير
اشيائ ارجاع شده باشند . درست قبل از اينكه يك داراي رها شود، سيستم حين اجراي
جاوا روش ()finalize را روي شي ئ فراخواني مي كند .
شكل عمومي روش ()finalize بقرار زير مي باشد :

protected void finalize)(
{
// finalization code here
}


دراينجا واژه كليدي protected توصيفگري است كه از دسترسي به روش ()finalize
توسط كدهاي تعريف شده خارج از كلاس جلوگيري مي كند.
مهم است بدانيد كه روش ()finalize درست مقدم بر جمع آوري زباله فراخواني
مي شود . بعنوان مثال وقتي يك شي ئ از قلمرو خارج مي شود ، اين روش فراخواني
نخواهد شد.اين بدان معني است كه نميتوانيد تشخيص بدهيد كه چه زماني ()finalize
اجرا خواهد شد و يا اصلا" اجرا نخواهد شد . بنابراين ، برنامه شما بايد ساير
وسائل براي آزاد كردن منابع سيستم مورد استفاده شي ئ را تدارك ببيند . برنامه
نبايد براي عمليات برنامه اي عادي ، متكي به روش ()finalize باشد .
نكته : اگر با C++ آشنايي داريد، پس مي دانيد كه C++ امكان مي دهد تا يك خراب
كننده (destructor) براي يك كلاس تعريف نماييد ، كه هرگاه يك شي ئ خارج
از قلمرو قرار گيرد ، فراخواني خواهد شد . جاوا چنين كاري نكرده و از
اين ايده پشتيباني نمي كند . روش ()finalize فقط به يك تابع خراب كننده
نزديك مي شود. به مرور كه تجربه بيشتري با جاوا كسب مي كنيد ، مي بينيد
كه نياز به توابع خراب كننده بسيار كم است زيرا زير سيستم جمع آوري حسن انجام مي دهد .

Nesta
01-07-2005, 07:43
دو دستور كنترلي

اين دو دستور يك جنبه بسيار مهم از جاوا يعني بلوك هاي كد (block of code)
را تشريح مي كنند .

دستور if(if statement()
دستور if در جاوا نظير دستور lf درهر يك از زبانهاي برنامه نويسي كار ميكند.
بعلاوه اين دستور از نظر قواعد صرف و نحو با دستور ifدر Cرو C++و شباهت دارد .
ساده ترين شكل آن را در زير مشاهده مي كنيد :

if( condition )statement;


در اينجا شرط (condition) يك عبارت بولي (Boolean) است . اگر شرايط درست
باشد ، آنگاه دستور اجرا خواهدشد . اگر شرايط صحيح نباشد ، آنگاه دستور پشت سر
گذاشته مي شود (bypassed). بعنوان مثال در نظر بگيريد :

+ if(num < 100 )println("num is less then 100");


در اين حالت ، اگر متغير num شامل مقداري كوچكتر از 100 باشد ، عبارت شرطي
درست بوده و ()println اجرا خواهد شد . اگر num شامل مقداري بزرگتر يا مساوي 100
باشد ، آنگاه روش ()println پشت سر گذاشته مي شود .
بعدا" خواهيد ديد كه جاوا يك ضميمه كامل از عملگرهاي رابطه اي (Relational)
تعريف مي كند كه قابل استفاده در عبارات شرطي هستند . چند نمونه از آنها بشرح
زير است :


|
مفهوم آن | عملگر |
|
كوچكتر از | < |
|
بزرگتر از | > |
|
مساوي با | = = |


دقت داشته باشيد كه آزمايش تساوي با علامت تساوي انجام مي گيرد .
در زير برنامه اي مشاهده مي كنيد كه يك دستور if را توصيف كرده است :

+ /*
+ Demonstrate the if.
+ Call this file "IfSample.java".
+ */
+ class IfSample {
+ public static void main( String args [] ){
+ int x/ y;
+
+ x = 10;
+ y = 20;
+ if(x < y )System.out.println("x is less than y");
+
+ x = x * 2;
+ if(x == y )System.out.println("x now equal to y");
+
+ x = x * 2;
+ if(x > y )System.out.println("x now greater than y");
+
+ // this won't display anything
+ if(x == y )System.out.println("you won't see this");
+ }
+ }


خروجي توليد شده توسط اين برنامه بشرح زير خواهد بود :

x is less than y
x now equal to y
x now greater than y


به يك نكته ديگر در اين برنامه دقت نماييد . خط

+ int x/ y;


دو متغير xو yو را با استفاده از فهرست جدا شده با كاما اعلان مي كند .

حلقه for
شايد از تجربيات قبلي در برنامه نويسي تا بحال فهميده باشيد كه دستورات
حلقه (loop statements) يك بخش بسيار مهم در كليه زبانهاي برنامه نويسي هستند.
جاوا نيز از اين قاعده مستثني نيست . در حقيقت همانگونه كه در فصل پنجم خواهيد
ديد ، جاوا يك دسته بندي پر قدرت از ساختارهاي حلقه اي عرضه مي كند . شايد از
همه اين ساختارها سليس تر حلقه for باشد . اگر با Cو C++و آشنايي داشته باشيد
خوشحال خواهيد شد كه بدانيد نحوه كار حلقه هاي for در جاوا با اين زبانها مشابه
است . اگر با Cو C++و آشنايي نداريد ، باز هم فراگيري استفاده از حلقه for
بسيار ساده خواهد بود . ساده ترين شكل اين حلقه بقرار زير مي باشد :

for( initialization; condition )statement;


دستور اجراي مكرر شرايط مقداردهي اوليه
بخش مقداردهي اوليه در يك حلقه در معمول ترين شكل خود يك مقدار اوليه را در
يك متغير كنترل اگر ماحصل اين آزمايش صحيح باشد ، حلقه for به تكرار خود ادامه
مي دهد . اگر حاصل ناصحيح باشد ، حلقه متوقف خواهد شد . عبارت اجراي مكرر
تعيين كننده اين است كه متغير كنترل حلقه پس از هر بار تكرار حلقه چگونه تغيير
خواهد كرد . برنامه كوتاه زير توصيف كننده يك حلقه for مي باشد :

+ /*
+ Demonstrate the for loop.
+ Call this file "ForTest.java".
+ */
+ class ForTest {
+ public static void main(String args [] ){
+ int x;
+
+ for(x = 0; x<10; x = x+1)
+ System.out.println("This is x :" + x);
+ }
+ }


اين برنامه ، خروجي زير را توليد خواهد نمود :

this is x:0
this is x:1
this is x:2
this is x:3
this is x:4
this is x:5
this is x:6
this is x:7
this is x:8
this is x:9


در اين مثال ، x متغير كنترل حلقه است . در بخش مقداردهي اوليه حلقه for به
اين متغير مقدار صفر داده مي شود. در شروع هر تكرار ( شامل مرحله اول ) آزمايش
شرط 10 اجرا خواهد شد ، و سپس بخش اجراي مكرر حلقه اجرا خواهد شد . اين روال ماداميكه
آزمايش شرايط صحيح باشد ، ادامه مي يابد .
بعنوان يك نكته قابل تامل ،در برنامه هاي حرفه اي نوشته شده توسط جاوا بندرت
بخش اجراي مكرر حلقه بصورت برنامه قبلي نوشته مي شود . يعني شما بندرت دستوري
مثل عبارت زير خواهيد ديد :

+ x = x + 1;


دليل اين است كه جاوا دربرگيرنده يك عملگر افزايشي ويژه است كه همين عمليات
را بطور موثرتري انجام مي دهد . اين عملگر افزايشي ++ است ( دو علامت جمع در
كنار هم ) . عملگر افزايشي ، عملوند خود را يكي يكي افزايش خواهد داد . با
استفاده از عملگر افزايشي دستور قبلي را مي توان بصورت زير نوشت :

+ x++;


بدين ترتيب for در برنامه قبلي را معمولا" بصورت زير مي نويسند :

+ for(x = 0; x<10; x++)


ممكن است بخواهيد اين مورد را آزمايش كنيد . همانطوريكه خواهيد ديد ، حلقه
درست مثل قبل و بهمان ترتيب اجرا خواهد شد .
جاوا همچنين يك عملگر كاهشي (decrement) فراهم نموده كه باعلامت (- -) مشخص يكي يكي كاهش خواهد داد .

مهمان
01-07-2005, 07:44
سلام نستا جان
من اين مطالبي که مي نويسيد را قبلا از روي يک منبع ديگه خواندم.
من منتظر قسمت J2ME هستم :)
برنامه نويسي براي موبايل :idea:

Nesta
01-07-2005, 07:44
كلاس پشته A stack class

اگرچه كلاس Box براي نشان دادن اجزائضروري يك كلاس مناسب بود، اما فاقد ارزش
عملي است . همانطوريكه از بحث برنامه نويسي شي ئ گرا (oop) بياد داريد ، يكي از
مزاياي بسيار مهم oop، كپسول سازي داده ها و كدي است كه با اين داده ها سر و كار
دارد . كلاس مكانيسمي است كه كپسول سازي در جاوا انجام مي گيرد. با خلق يك كلاس
شما نوع جديدي از داده را ايجاد مي كنيد كه هم طبيعت داده هاي مورد استفاده و
هم روالهاي ضروري براي كار با داده ها را تعريف مي كند . علاوه بر اين ، روشها
يك رابط پايدار و كنترل شده به داده هاي كلاس را تعريف مي كنند . بدين ترتيب
مي توانيد از طريق روشهاي يك كلاس از آن كلاس استفاده نماييد بدون اينكه نگران
جزئيات پياده سازي كلاس باشيد و يا اينكه نگران باشيد كه داده ها واقعا" چگونه
داخل آن كلاس مديريت مي شوند .
در يك مضمون ، يك كلاس شبيه يك " موتور داده "(data engine() است . براي كار
با موتور از طريق ابزارهاي كنترل كننده اش ، نيازي به دانش و اشراف كامل بر
چگونگي كاركرد داخلي موتور نداريد . در حقيقت ، از آنجاييكه جزئيات پنهان
شده اند ، مي توان كاركرد داخلي آن را بر حسب نياز تغيير داد . ماداميكه كد شما
كلاس را از طريق روشهايش استفاده مي كند ، مي توان جزئيات دروني را بدون ايجاد
اثرات جانبي در خارج كلاس تغيير داد .
پشته (stack) ، داده ها را بر حسب آنچه اول آمده آخر بيرون مي رود ذخيره
مي كند . بنابراين پشته شبيه يك پشته از بشقابهاي روي هم چيده است . اولين
بشقاب قرار گرفته روي ميز ، آخرين بشقابي است كه از آنجا خارج مي شود . پشته ها
بطور سنتي از طريق دو عمل نشاندن (push) و پراندن (pop) كنترل مي شوند . براي
نهادن يك قلم روي پشته ، از push استفاده مي كنيم . براي بيرون آوردن يك قلم
از پشته ، از pop استفاده مي كنيم . خواهيد ديد كه كپسول سازي كل مكانيسم پشته
بسيار ساده است .
در اينجا يك كلاس تحت نام stack وجود دارد كه يك پشته را براي اعداد صحيح
پياده سازي مي كند :

+ // This class defines an integer stack that can hold 10 values.
+ class Stack {
+ int stck[] = new int[10];
+ int tos;
+
+ // Initialize top-of-stack
+ Stack )({
+ tos =- 1;
+ }
+
+ // Pash an item onto the stack
+ void push(int item ){
+ if(tos==9)
+ System.out.println("Stack is full.");
+ else
+ stck[++tos] = item;
+ }
+
+ // Popan item from the stack
+ int pop )({
+ if(tos < 0 ){
+ System.out.println("Stack underflow.");
+ return 0;
+ }
+ else
+ return stck[tos--];
+ }
+ }


همانطوريكه مي بينيد ، كلاس stack دو قلم داده و سه روش را تعريف مي كند .
پشته اعداد صحيح توسط آرايه stck نگهداري مي شود . اين آرايه توسط متغير tos
نمايه سازي مي شود كه همواره نمايه بالاي پشته را نشان مي دهد . سازنده ()stack
متغير tos را با عدد 1- مقدار دهي اوليه مي كند ، كه نشان دهنده يك پشته خالي
است . روش ()push يك قلم را روي پشته مي نشاند . براي بازيابي يك قلم از پشته
روش ()pop را فراخواني مي كنيم . از آنجاييكه دسترسي به پشته توسط ()push و
()pop انجام مي گيرد ، اين حقيقت كه پشته توسط يك آرايه نگهداري مي شود واقعا"
با استفاده از پشته مرتبط نيست . بعنوان مثال پشته بايد در يك ساختار پيچيده تر
داده نگهداري شود ، نظير فهرست پيوندي (linked list) ، اما رابط تعريف شده
بوسيله ()push و ()pop همچنان دست نخورده باقي مي ماند .
كلاس Test stack كه در زير نشان داده ايم ، نشان دهنده كلاس stack است . اين
كلاس دو پشته عدد صحيح ايجاد كرده ، برخي مقادير را روي هر يك قرار داده و سپس
آن مقادير را مي پراند .

+ class TestStack {
+ public static void main(String args[] ){
+ Stack mystack1 = new Stack)(;
+ Stack mystack2 = new Stack)(;
+
+ // push some numbers onto the stack
+ for(int i=0; i<10; i++ )mystack1.push(i);
+ for(int i=10; i<20; i++ )mystack2.push(i);
+
+ // pop those numbers off the stack
+ System.out.println("Stack in mystack1:");
+ for(int i=0; i<10; i++)
+ System.out.println(mystack1.pop))(;
+
+ System.out.println("Stack in mystack2:");
+ for(int i=0; i<10; i++)
+ System.out.println(mystack2.pop))(;
+ }
+ }


اين برنامه خروجي زير را توليد مي كند :

Stack in mystack1:
9
8
7
6
5
4
3
2
1
0
Stack in mystack2:
19
18
17
16
15
14
13
12
11
10


همانطوريكه مي بينيد ، محتوي هر يك از پشته ها جداگانه است .
يك نكته ديگر درباره كلاس stack. همانطوريكه اخيرا" پياده سازي شده است ، براي
آرايه اي كه پشته را نگهداري مي كند يعني stck امكان دارد توسط كد خارج از كلاس stack
مورد تغيير قرار گيرد. اين حالت stack را براي سوئاستفاده يا استفاده هاي

Nesta
01-07-2005, 07:44
نگاهي دقيق تر به روشها و كلاسها

از اين پس موضوعات مربوط به روشها، شامل انباشتن (over loading) ، گذر دادن
پارامترها(parameter passing) و خود فراخواني يا همان برگشت پذيري (recursion)
را بررسي مي كنيم . و درباره كنترل دسترسي ، استفاده از واژه كليدي Static و
يكي از مهمترين كلاسهاي توكار جاوا يعني string بحت خواهيم نمود .

Nesta
01-07-2005, 07:45
انباشتن روشها

در جاوا اين امكان وجود دارد كه دو يا چند روش را داخل يك كلاس كه همان نام
را دارد تعريف نمود ، البته ماداميكه اعلان پارامترهاي آن روشها متفاوت باشد .
در چنين شرايطي ، روشها را مي گويند " انباشته شده " و اين نوع پردازش را "
انباشتن روش " مي نامند . انباشتن روش يكي از راههايي است كه جاوا بوسيله آن "
چند شكلي " را پياده سازي مي كند . اگر تا بحال از زباني كه امكان انباشتن
روشها را دارد استفاده نكرده ايد ، اين مفهوم در وهله اول بسيار عجيب بنظر
مي رسد . اما خواهيد ديد كه انباشتن روش يكي از جنبه هاي هيجان انگيز و سودمند
جاوا است .
وقتي يك روش انباشته شده فراخواني گردد ، جاوا از نوع و يا شماره آرگومانها
بعنوان راهنماي تعيين روايت (Version) روش انباشته شده اي كه واقعا" فراخواني
مي شود ، استفاده مي كند . بدين ترتيب ، روشهاي انباشته شده بايد در نوع و يا
شماره پارامترهايشان متفاوت باشند . در حاليكه روشهاي انباشته شده ممكن است
انواع برگشتي متفاوتي داشته باشند ، اما نوع برگشتي بتنهايي براي تشخيص دو
روايت از يك روش كافي نخواهد بود. وقتي جاوا با يك فراخواني به يك روش انباشته
شده مواجه مي شود ، خيلي ساده روايتي از روش را اجرا مي كند كه پارامترهاي آن
با آرگومانهاي استفاده شده در فراخواني مطابقت داشته باشند .
در اينجا يك مثال ساده وجود دارد كه نشان دهنده انباشتن روش مي باشد :

+ // Demonstrate method overloading.
+ class OverloadDemo {
+ void test )({
+ System.out.println("No parameters");
+ }
+
+ // Overload test for one integer parameter.
+ void test(int a ){
+ System.out.println("a :" + a);
+ }
+
+ // Overload test for two integer parameters.
+ void test(int a/ int b ){
+ System.out.println("a and b :" + a + " " + b);
+ }
+
+ // Overload test for a double parameter.
+ double test(double a ){
+ System.out.println("double a :" + a);
+ return a*a;
+ }
+ }
+
+ class Overload {
+ public static void main(String args[] ){
+ OverloadDemo ob = new OverloadDemo)(;
+ double result;
+
+ // call all versions of test)(
+ ob.test)(;
+ ob.test(10);
+ ob.test(10/ 20);
+ result = ob.test(123.2);
+ System.out.println("Result of ob.test(123.2 :)" + result);
+ }
+ }


اين برنامه خروجي زير را توليد مي كند :

No parameters
a :10
a and b :10 20
double a :123.2
Result of ob.test(123.2 :)15178.2


همانطوريكه مي بينيد ، ()test چهار بار انباشته شده است . اولين روايت
پارامتري نمي گيرد ، دومين روايت يك پارامتر عدد صحيح مي گيرد ، سومين روايت
دو پارامتر عدد صحيح مي گيرد و چهارمين روايت يك پارامتر double مي گيرد . اين
حقيقت كه چهارمين روايت ()test همچنين مقداري را برمي گرداند، هرگز نتيجه حاصل
از عمل انباشتن نيست ، چون انواع برگشتي نقشي در تجزيه و تحليل انباشت ندارند.
وقتي يك روش انباشته شده فراخواني ميشود،جاوا بدنبال تطبيقي بين آرگومانهاي
استفاده شده براي فراخواني روش و پارامترهاي آن روش مي گردد . اما ، اين تطابق
نبايد لزوما" هميشه صحيح باشد. در برخي شرايط تبديل انواع خودكار جاوا ميتواند
نقشي در تجزيه و تحليل انباشت داشته باشد . بعنوان مثال ، برنامه بعدي را در
نظر بگيريد :

+ // Automatic type conversions apply to overloading.
+ class OverloadDemo {
+ void test )({
+ System.out.println("No parameters");
+ }
+
+ // Overload test for two integer parameters.
+ void test(int a/ int b ){
+ System.out.println("a and b :" + a + " " + b);
+ }
+
+ // Overload test for a double parameter.
+ double test(double a ){
+ System.out.println("Inside test(double )a :" + a);
+ }
+ }
+
+ class Overload {
+ public static void main(String args[] ){
+ OverloadDemo ob = new OverloadDemo)(;
+ int i = 88;
+
+ ob.test)(;
+ ob.test(10/ 20);
+
+ ob.test(i); // this will invoke test(double)
+ ob.test(123.2); // this will invoke test(double)
+ }
+ }


اين برنامه خروجي زير را توليد مي كند :

No parameters
a and b :10 20
Inside test(double )a :88
Inside test(double )a :123.2


همانطوريكه مشاهده ميكنيد، اين روايت ازoverloadDemo تعريف كننده (int)test
نمي باشد . بنابراين هنگاميكه ()test همراه با يك آرگومان عدد صحيح داخل overload
فراخواني مي شود ، هيچ روش تطبيق دهنده پيدا نخواهد شد . اما جاوا
مي تواند بطور خودكار يك عدد صحيح را به يك double تبديل نمايد و اين تبديل
براي رفع فراخواني مورداستفاده قرار ميگيرد. بنابراين ، بعد از آنكه (int)test
پيدا نمي شود ، جاوا i را به double ارتقائ داده و آنگاه (double)test را
فراخواني مي كند . البته اگر (int)test تعريف شده بود ، فراخواني مي شد . جاوا
فقط در صورتي كه هيچ تطبيق دقيقي پيدا نكند ، از تبديل خودكار انواع استفاده
مي كند .
انباشتن روش از چند شكلي هم پشتيباني مي كند زيرا يكي از شيوه هايي است كه
جاوا توسط آن الگوي " يك رابط و چندين روش " را پياده سازي مي كند . براي درك
اين مطلب ، مورد بعدي را درنظر بگيريد.در زبانهايي كه از انباشتن روش پشتيباني
نمي كنند ، هر روش بايد يك اسم منحصر بفرد داشته باشد . اما غالبا" مي خواهيد
يك روش را براي چندين نوع داده مختلف پياده سازي نماييد . مثلا" تابع قدر مطلق
را در نظر بگيريد . در زبانهايي كه از انباشتن روش پشتيباني نمي كنند معمولا"
سه يا چند روايت مختلف از اين تابع وجود دارد ، كه هر يك اسم متفاوتي اختيار
مي كند . بعنوان نمونه ، در زبان C تابع ()abs قدر مطلق يك عدد صحيح را
برمي گرداند ، ()labs قدر مطلق يك عدد صحيح long را برمي گرداند ، ()fabs قدر
مطلق يك عدد اعشاري را برمي گرداند . از آنجاييكه زبان C از انباشتن روش
پشتيباني نمي كند ، هر تابع بايد اسم خاص خودش را داشته باشد ، حتي اگر هر سه
تابع يك وظيفه واحد را انجام دهند. از نظر ذهني اين حالت ، شرايط پيچيده تري را
نسبت به آنچه واقعا" وجود دارد ، ايجاب مي كند . اگرچه مفهوم اصلي اين توابع
يكسان است ، اما همچنان مجبوريد سه اسم را بخاطر بسپاريد . اين شرايط در جاوا
اتفاق نمي افتد ، زيرا تمامي روش هاي مربوط به قدر مطلق مي توانند از يك اسم
واحد استفاده نمايند . در حقيقت كتابخانه كلاس استاندارد جاوا Java's standard)
(class library شامل يك روش قدر مطلق موسوم به ()abs مي باشد . اين روش توسط
كلاس Math در جاوا انباشته شده تا كليه انواع رقمي را مديريت نمايد . جاوا بر
اساس نوع آرگومان ، تصميم مي گيرد كه كدام روايت از ()abs را فراخواني نمايد .
ارزش انباشتن روشها در اين است كه مي توان با استفاده از يك اسم مشترك به
كليه روشهاي مرتبط با هم دسترسي پيدا كرد. بدين ترتيب ،اسم abs معرف عمل عمومي
است كه اجرا خواهد شد . تعيين روايت مخصوص براي هر يك از شرايط خاص بر عهده
كامپايلر مي باشد . برنامه نويس فقط كافي است تا اعمال عمومي كه بايد انجام
شوند را بخاطر بسپارد . بدين ترتيب با استفاده از مفهوم چند شكلي ، چندين اسم
به يك اسم خلاصه شده اند. اگرچه اين مثال بسيار ساده بود، امااگر مفهوم زيربنايي
آن را گسترش دهيد ، مي فهميد كه انباشتن روشها تا چه حد در مديريت پيچيدگي در
برنامه ها سودمند و كارساز است .
وقتي يك روش را انباشته مي كنيد ، هر يك از روايتهاي آن روش قادرند هر نوع
عمل مورد نظر شما را انجام دهند. هيچ قانوني مبني بر اينكه روشهاي انباشته شده
بايد با يكديگر مرتبط باشند، وجود ندارد. اما از نقطه نظر روش شناسي ، انباشتن
روشها مستلزم يك نوع ارتباط است . بدين ترتيب ، اگرچه مي توانيد از يك اسم
مشترك براي انباشتن روشهاي غير مرتبط با هم استفاده نماييد ، ولي بهتر است اين
كار را انجام ندهيد . بعنوان مثال ، مي توانيد از اسم sqr براي ايجاد روشهايي
كه مربع يك عدد صحيح و ريشه دوم عدد اعشاري را برمي گرداند ، استفاده نماييد .
اما اين دو عمل كاملا" با يكديگر متفاوتند. بكارگيري انباشتن روش درچنين مواقعي
سبب از دست رفتن هدف اصلي اين كار خواهد شد. در عمل ، فقط عمليات كاملا" نزديك
بهم را انباشته مي كنيد .

انباشتن سازندگان Overloading constructors
علاوه بر انباشتن روشهاي معمولي ، مي توان روشهاي سازنده را نيز انباشته
نمود. در حقيقت براي اكثر كلاسهايي كه در دنياي واقعي ايجاد مي كنيد ، سازندگان
انباشته شده بجاي استثنائ يك عادت هستند .
در زير آخرين روايت Box را مشاهده مي كنيد :

+ class Box {
+ double width;
+ double height;
+ double depth;
+
+ // This is the constructor for Box.
+ Box(double w/ double h/ double d ){
+ width = w;
+ height = h;
+ depth = d;
+ }
+
+ // compute and return volume
+ double volume )({
+ return width * height * depth;
+ }
+ }


همانطوريكه مي بينيد ، سازنده ()Box نيازمند سه پارامتر است . يعني كليه
اعلانات اشيائ Box بايد سه آرگومان به سازنده ()Box بگذرانند . بعنوان مثال
دستور بعدي فعلا" نامعتبر است : + Box ob = new Box)(;

ازآنجاييكه ()Box نيازمند سه آرگومان است ، فراخواني آن بدون آرگومانها خطا
است . اين مورد، سوالات مهمي را پيش رو قرار مي دهد. اگر فقط يك box را بخواهيد
و اهميتي نمي دهيد و يا نمي دانيد كه ابعاد اوليه آن چه بوده اند ، چه پيش
مي آيد ? همچنين ممكن است بخواهيد يك مكعب را با مشخص كردن يك مقدار كه براي
كليه ابعاد آن استفاده مي شوند، مقدار دهي اوليه نماييد ? آنگونه كه قبلا" كلاس Box
نوشته شده ، اين گزينه ها در دسترس شما نخواهد بود .
خوشبختانه راه حل اين مشكلات كاملا" ساده است : خيلي ساده تابع سازنده Box را
انباشته كنيد بگونه اي كه شرايط توصيف شده را اداره نمايد . برنامه بعدي شامل
يك روايت توسعه يافته Box است كه اينكار را انجام مي دهد :

+ /* Here/ Box defines three constructors to initialize
+ the dimensions of a box various ways.
+ */
+ class Box {
+ double width;
+ double height;
+ double depth;
+ // constructor used when all dimensions specified
+ Box(double w/ double h/ double d ){
+ width = w;
+ height = h;
+ depth = d;
+ }
+
+ // constructor used when no dimensions specified
+ Box )({
+ width =- 1; // use- 1 to indicate
+ height =- 1; // an uninitialized
+ depth =- 1; // box
+ }
+
+ // constructor used when cube is created
+ Box(double len ){
+ width = height = deoth = len;
+ }
+
+ // compute and return volume
+ double volume )({
+ return width * height * depth;
+ }
+ }
+
+ class OverloadDemo {
+ public static void main(String args[] ){
+ // create boxes using the various constructors
+ Box mybox1 = new Box(10/ 20/ 15);
+ Box mybox2 = new Box)(;
+ Box mycube = new Box(7);
+
+ double vol;
+
+ // get volume of first box
+ vol = mybox1.volume)(;
+ System.out.println("Volume of mybox1 is " + vol);
+
+ // get volume of second box
+ vol = mybox2.volume)(;
+ System.out.println("Volume of mybox2 is " + vol);
+
+ // get volume of cube
+ vol = mycube.volume)(;
+ System.out.println("Volume of mycube is " + vol);
+ }
+ }


خروجي اين برنامه بقرار زير مي باشد :

Volume of mybox1 is 3000
Volume of mybox2 is- 1
Volume of mycube is 343

ne اجرا مي شود ، پارامترها را مشخص

Nesta
01-07-2005, 07:46
استفاده از اشيائ بعنوان پارامترها

تاكنون فقط از انواع ساده بعنوان پارامترهاي روشها استفاده كرده ايم . اما
هم صحيح و هم معمول است كه اشيائ را نيز به روشها گذر دهيم . بعنوان مثال
برنامه ساده بعدي را در نظر بگيريد :

+ // Objects may be passed to methods.
+ class Test {
+ int a/ b;
+ Test(int i/ int j ){
+ a = i;
+ b = j;
+ }
+
+ // return true if o is equal to the invoking object
+ boolean equals(Test o ){
+ if(o.a == a && o.b == b )return true;
+ else return false;
+ }
+ }
+
+ class PassOb {
+ public static void main(String args[] ){
+ Test ob1 = new Test(100/ 22);
+
+ Test ob2 = new Test(100/ 22);
+ Test ob3 = new Test-(1/- 1);
+
+ System.out.println("ob1 == ob2 :" + ob1.equals(ob2));
+
+ System.out.println("ob1 == ob3 :" + ob1.equals(ob3));
+ }
+ }


اين برنامه ، خروجي بعدي را توليد مي كند :

ob1 == ob2 :true
ob1 == ob3 :false


همانطوريكه مشاهده ميكنيد، روش ()equals داخل Test دو شي ئ را از نظر كيفيت
مقايسه نموده و نتيجه را برمي گرداند . يعني اين روش ، شي ئ فراخواننده را با
شيئي كه گذر كرده مقايسه مي كند . اگر محتوي آندو يكسان باشد ، آنگاه روش true
را برمي گرداند . در غير اينصورت false را برمي گرداند . توجه داشته باشيد كه
پارامتر o در ()equals مشخص كننده Test بعنوان نوع آن مي باشد. اگرچه Test يك
نوع كلاس ايجاد شده توسط برنامه است ،اما بعنوان انواع توكار جاوا و بهمان روش
مورد استفاده قرار گرفته است .
يكي از رايجترين كاربردهاي پارامترهاي شيئي مربوط به سازندگان است . غالبا"
ممكن است بخواهيد يك شي ئ جديد را بسازيد طوري كه اين شي ئ در ابتدا نظير يك شي ئ
موجود باشد. براي انجام اينكار بايد يك تابع سازنده تعريف نماييد كه يك شي ئ از
كلاس خود را بعنوان يك پارامتر انتخاب مي كند . بعنوان مثال ، روايت بعدي از
()Box به يك شي ئ امكان داده تا آغازگر ديگري باشد :

+ // Here/ Box allows one object to initialize another.
+ class Box {
+ double width;
+ double height;
+ double depth;
+
+ // construct clone of an object
+ Box(Box ob ){ // pass object to constructor
+ width = ob.width;
+ height = ob.height;
+ depth = ob.depth;
+ }
+
+ // constructor used when all dimensions specified
+ Box(double w/ double h/ double d ){
+ width = w;
+ height = h;
+ depth = d;
+ }
+
+ // constructor used when no dimensions specified
+ Box )({
+ width =- 1; // use- 1 to indicate
+ height =- 1; // an uninitialized
+ depth =- 1; // box
+ }
+
+ // constructor used when cube is created
+ Box(double len ){
+ width = height = depth
+ }
+
+ // compute and return volume
+ double volume )({
+ return width * height * depth;
+ }
+ }
+
+ class OverloadCons2 {
+ public static void main(String args[] ){
+ // create boxes using the various constructors
+ Box mybox1 = new Box(10/ 20/ 15);
+ Box mybox2 = new Box)(;
+ Box mycube = new Box(7);
+
+ Box myclone = new Box(mybox1);
+
+ double vol;
+
+ // get volume of first box
+ vol = mybox1.volume)(;
+ System.out.println("Volume of mybox1 is " + vol);
+
+ // get volume of second box
+ vol = mybox2.volume)(;
+ System.out.println("Volume of mybox2 is " + vol);
+
+ // get volume of cube
+ vol = mycube.volume)(;
+ System.out.println("Volume of cube is " + vol);
+
+ // get volume of clone
+ vol = myclone.volume)(;
+ System.out.println("Volume of clone is " + vol);
+ }
+ }


بعدا" خواهيد ديد كه وقتي شروع به ايجاد كلاسهاي خود مي نماييد، معمولا" براي
اينكه اجازه دهيم تا اشيائ بصورتي موثر و آسان ساخته شوند ، لازم است اشكال هاي سازنده را فراهم آوريم .

Nesta
01-07-2005, 07:48
نگاهي دقيق تر به گذر دادن آرگومانها

در كل ، دو راه وجود دارد تا يك زبان كامپيوتري يك آرگومان را به يك زير
روال گذر دهد. اولين راه " فراخواني بوسيله مقدار "(call-by-value() است . اين
روش مقدار يك آرگومان را در پارامتر رسمي زير روال كپي مي كند . بنابراين
تغييراتي كه روي پارامتر زير روال اعمال مي شود ، تاثيري بر آرگوماني كه براي
فراخواني آن استفاده شده نخواهد داشت . دومين راهي كه يك آرگومان مي تواند گذر
كند " فراخواني بوسيله ارجاع "(call-by-reference() است . در اين روش ، ارجاع
به يك آرگومان ( نه مقدار آن آرگومان ) به پارامتر گذر داده مي شود . داخل زير
روال از اين ارجاع براي دسترسي به آرگومان واقعي مشخص شده در فراخواني استفاده
مي شود . اين بدان معني است كه تغييرات اعمال شده روي پارامتر ، روي آرگوماني
كه براي فراخواني زير روال استفاده شده ، تاثير خواهد داشت . خواهيد ديد كه
جاوا از هر دو روش برحسب اينكه چه چيزي گذر كرده باشد ، استفاده مي كند .
در جاوا ، وقتي يك نوع ساده را به يك روش گذر مي دهيد ، اين نوع بوسيله
مقدارش گذر ميكند . بنابراين ، آنچه براي پارامتري كه آرگومان را دريافت ميكند
اتفاق بيفتد هيچ تاثيري در خارج از روش نخواهد داشت . بعنوان مثال ، برنامه
بعدي را در نظر بگيريد :

+ // Simple types are passed by value.
+ class Test {
+ void meth(int i/ int j ){
+ i *= 2;
+ j /= 2;
+ }
+ }
+
+ class CallByValue {
+ public static void main(String args[] ){
+ Test ob = new Test)(;
+ int a = 15/ b = 20;
+
+ System.out.println("a and b before call :" +
+ a + " " + b);
+
+ ob.meth(a/ b);
+
+ System.out.println("a and b after call :" +
+ a + " " + b);
+ }
+ }


خروجي برنامه فوق بقرار زير مي باشد :

a and b before call :15 20
a and b after call :15 20


بخوبي مشاهده مي كنيد كه عمليات اتفاق افتاده داخل ()meth هيچ تاثيري روي
مقادير aو bو در فراخواني استفاده شده اند، نخواهد داشت . در اينجا مقادير آنها
به 30 و 10 تغيير نمي يابد .
وقتي يك شي ئ را به يك روش گذر مي دهيد ، شرايط بطور مهيجي تغيير مي كند
زيرا اشيائ بوسيله ارجاعشان گذر داده مي شوند . بياد آوريد كه وقتي يك متغير
از يك نوع كلاس ايجاد مي كنيد ، شما فقط يك ارجاع به شي ئ خلق مي كنيد . بدين
ترتيب ، وقتي اين ارجاع را به يك روش گذر مي دهيد ، پارامتري كه آن را دريافت
مي كند . بهمان شي ئ ارجاع مي كند كه توسط آرگومان به آن ارجاع شده بود . اين
بدان معني است كه اشيائ با استفاده از طريقه " فراخواني بوسيله ارجاع " به
روشها گذر داده مي شوند. تغييرات اشيائ داخل روش سبب تغيير شيئي است كه بعنوان
يك آرگومان استفاده شده است . بعنوان مثال ، برنامه بعدي را در نظر بگيريد :

+ // Objects are passed by reference.
+
+ class Test {
+ int a/ b;
+
+ Test(int i/ int j ){
+ a = i;
+ b = j;
+ }
+
+ // pass an object
+ void meth(Test o ){
+ o.a *= 2;
+ o.b /= 2;
+ }
+ }
+
+ class CallByRef {
+ public static void main(String args[] ){
+ Test ob = new Test(15/ 20);
+
+ System.out.println("ob.a and ob.b before call :" +
+ ob.a + " " + ob.b);
+
+ ob.meth(ob);
+
+ System.out.println("ob.a and ob.b after call :" +
+ ob.a + " " + ob.b);


برنامه فوق ، خروجي زير را توليد مي كند :

ob.a and ob.b before call :15 20
ob.a and ob.b after call :30 10


همانطوريكه مي بينيد ، در اين حالت ، اعمال داخل ()meth ، شيئي را كه بعنوان
يك آرگومان استفاده شده تحت تاثير قرار داده است .
يك نكته جالب توجه اينكه وقتي يك ارجاع شي ئ به يك روش گذر داده مي شود، خود
ارجاع از طريق " فراخواني بوسيله مقدار " گذر داده مي شود . اما چون مقداري كه
بايد گذر داده شود خودش به يك شي ئ ارجاع مي كند ، كپي آن مقدار همچنان به همان
شي ئ ارجاع مي كند كه آرگومان مربوطه ارجاع مي كند .
ياد آوري : وقتي يك نوع ساده به يك روش گذر داده ميشود اينكار توسط " فراخواني
بوسيله مقدار " انجام ميگيرد. اشيائتوسط " فراخواني بوسيله ارجاع "
گذر داده مي شوند .

برگرداندن اشيائ
يك روش قادر است هر نوع داده شامل انواع كلاسي كه ايجاد ميكنيد را برگرداند.
بعنوان مثال ، در برنامه بعدي روش ()incrByTen يك شي ئ را برمي گرداند كه در آن
مقدار a ده واحد بزرگتر از مقدار آن در شي ئ فراخواننده است .

+ // Returning an object.
+ class Test {
+ int a;
+
+ Test(int i ){
+ a = i;
+ }
+
+ Test incrByTen )({
+ Test temp = new Test(a+10);
+ return temp;
+ }
+ }
+
+ class RetOb {
+ public static void main(String args[] ){
+ Test ob1 = new Test(2);
+ Test ob2;
+ ob2 = ob1.incrByTen)(;
+ System.out.println("ob1.a :" + ob1.a);
+ System.out.println("ob2.a :" + ob2.a);
+
+ ob2 = ob2.incrByTen)(;
+ System.out.println("ob2.a after second increase :"
+ + ob2.a);
+ }
+ }


خروجي برنامه فوق بقرار زير مي باشد :

ob1.a :2
ob2.a :12
ob2.a after second increase :22


همانطوريكه مشاهده مي كنيد ، هر بار كه ()incrByTen فراخوانده مي شود ، يك
شي ئ جديد توليد شده و يك ارجاع به آن شي ئ جديد به روال فراخواننده برگردان
مي شود .
مثال قبلي يك نكته مهم ديگر را نشان ميدهد : از آنجاييكه كليه اشيائ بصورت
پويا و با استفاده از new تخصيص مي يابند ، نگراني راجع به شيئي كه خارج از
قلمرو برود نخواهيد داشت ، زيرا در اين صورت روشي كه شي ئ درآن ايجاد شده پايان
خواهد گرفت . يك شي ئ ماداميكه از جايي در برنامه شما ارجاعي به آن وجود داشته
باشد ، زنده خواهد ماند . وقتي كه ارجاعي به آن شي ئ وجود نداشته باشد ، دفعه مرمت خواهد شد .

Nesta
01-07-2005, 07:51
سلام نستا جان
من اين مطالبي که مي نويسيد را قبلا از روي يک منبع ديگه خواندم.
من منتظر قسمت J2ME هستم :)
برنامه نويسي براي موبايل :idea:
سلام دوست عزیز شما فرمودید که از پای شروع کن من از پای شروع کردم برای موبایل باید صبر کنین که آماده کنم .من همه چی‌ می‌گذارم اگه باشه واسه موبایل هم میدم .یعنی‌ شما همه اینرو بلدین فقط گیرتون موبایل هست من دارم از بالا میم پائین

Nesta
01-07-2005, 07:55
طراحي و توليد برنامه هاي سازمان مقياس ( Enterprise-Level -- منظور نرم افزارهائي است كه با تكنولوژي هاي چند لايه [N-tier ] و براي محيطهائي وسيع با كاربردهاي مختلف - پلت فرمهاي متفاوت و كاربران غير همگن طراحي ميشوند ) با استفاده از تكنولوژي نه چندان جديد J2EE برخلاف محيطهاي ديگر ( ابزارهاي مايكروسافت و بورلند ) فوق العاده پيچيده و دشوار است و عملا هزينه اي كه بر دپارتمان نرم افزار تحميل ميكند در مقابل ديگر ابزارهاي به هيچ وجه توجيه پذير نيست و شايد تنها كليد حياتي و راز بقاي جاوا مستقل از محيط بودن ( Platform-independent ) آن است . برنامه نويسان حرفه اي جاوا بسيار نادر و حرفه اي هاي EJB بسيار كمياب هستند . ( EJB = enterprise Jaba beans -- با قدري تسامح و بيان غير دقيق تكنولوژي مشابه COM مايكروسافت در عالم جاوا )

اما هر چه بود گذشت !!! امروز جاوا به لطف آپتيمال جي ( OptimalJ ) داراي ابزاري براي توسعه سريع نرم افزار ها و كامپوننتها ( اجزاي مستقل توليد نرم افزار ) است كه با ابزارهاي مشابه مايكروسافت و بورلند قابل مقايسه و در برخي موارد برتر است !

آپتيمال جي داراي محيط توسعه اي Model-Driven است . به اين مفهوم كه شما درست مثل يك گرافيست ( شايد هم درست مثل يك مدير با تدبير !!! ) نرم افزار خود را نقاشي (!) ميكنيد و آپتيمال جي زحمت نگارش كد جاوا را خواهد كشيد آنهم نه پس از صدور دستوري شبيه به كامپايل ! خير ! .. درست همزمان ! ... شما مولفه هاي نرم افزار و رابطه بين آنها و همچنين مجموعه وظايف هر قطعه را * طراحي* ميكنيد و همزمان محيط آپتيمال جي براي شما كد مينويسد .

مژده اي هم براي توسعه دهندگان برنامه هاي وب ( Web Application ) ! آپتيمال جي به همراه خود يك وب سرور قدرتمند دروني و همچنين يك موتور اجراي سرولت ( Servlet Engine ) دارد كه شما را از همه چيز غير از خود بي نياز ميكند . ضمن اينكه نگران توسعه نرم افزار خود روي محيطهاي اجراي آن نباشيد ! ( Deployment ) آپتيمال جي با توجه به نوع پروژه و مواد مورد نياز آن براي آماده سازي محيط اجرا همه كارها را خودكار كرده است . شما ميتوانيد برنامه هاي خود ( به عنوان مثال سيستم مديريت اي ميل يك وب سايت ) را روي محيط خود بنويسيد و تست كنيد و با يك كيليك به محيط مورد نظر منتقل كنيد بدون اينكه درگير تهيه پكيجهاي كامل از امكانات نرم افزار و انتقال آنها باشيد .

آپتيمال جي درست مثل محيطهاي توسعه نرم افزار مبتني بر كامپوننت ( Component - Based ) مثل سي شارپ - ويژوال سي - دلفي - ويژوال بيسيك و ... داراي يك محيط توسعه مجتمع نرم افزار ( IDE ) قدرتمند است ( بسيار شبيه به محيط دات نت ) اما آنچه شما با آن سر و كار داريد اجزاي UML است نه كامپوننتهاي ويژوال و غير ويژوال و توابع و پراسيجر ها و كلاسها ! اين ابزار با بقيه محيطهاي توليد UML مثل رشنال رز يا مدل ميكر كاملا سازگار بوده و اگر طرحي براي برنامه دات نت خود آماده كرده ايد حالا ميتوانيد فقط با استفاده از همان طرح و قابليتهاي بي نظير آپتيمال جي با چند كيليك ساده و نهايتا نوشتن چند سطر كد مجموعه برنامه را با جاوا هم داشته باشيد !!!

آپتيمال جي همچنين رابطهاي قدرتمندي به نرم افزارهاي مديريت بانكهاي اطلاعاتي ( RDBMS ) معروف مثل اوراكل - اسكوئل سرور و ... دارد و همچنين با استاندارد JDBC براي برقراري هر بانك اطلاعاتي ( خصوصا JdataStore بورلند كه اولين بانك اطلاعاتي طراحي شده با جاوا بود ) سازگار با جاوا دارد .

قابليت توليد شي گرا و مبتني بر مدل EJB ها و همچنين صفحات ديناميك وب مبتني بر جاوا ( Java server pages ) از ديگر توانائي هاي قابل ذكر اين مجموعه است . ( نكته قابل توجه اين است كه محيط مبتني بر مدل آپتيمال جي براي طراحي كلاسهاي پايه اي مثل EJB ها بر خلاف محصولات مايكروسافت و بورلند فقط بدنه و رابطهاي كلاس را توليد نميكند ! بلكه زحمت نگارش كد را هم از دوش شما برداشته و بطور كامل كدهاي جاواي كلاس مورد نظر را طبق طراحي شما مينويسد ! .. بدين وسيله حتي بدون نگارش يك خط كد جاوا و داشتن آشنائي مقدماتي با جاوا و تخصص در زمينه UML ميتوانيد حرفه اي ترين EJB ها را جهت استفاده سازماني يا كاربردهائي مثل JSP توليد كنيد ! شعار *پروداكتيويتي اصل است* اينبار واقعا تحقق پيدا كرده است ! )

نكته قابل ذكر ديگر قدرت و سرعت توليد برنامه هاي رابط بانك اطلاعاتي ست . با ابزارهاي كارآمد موجود در اين مجموعه ( Domain Model و توليد Database Model از آن ) حتي آپتيمال جي كدهاي اسكوئل لازم براي توليد بانكها - جدولها و View هاي شما را هم خواهد نوشت . نيازي به دانستن SQL براي طراحي بانك اطلاعاتي نيست !

آپتيمال جي ( درست مثل ويژوال استوديو دات نت ) در يك محيط يكتا به شما امكان توليد برنامه هاي كاربردي ( فرض كنيد يك برنامه گرافيكي يا ويرايش فيلم يا حتي JphotoShop !!!! ) و برنامه هاي وب ( فرض كنيد سيستم ثبت نام آنلاين دانشجويان براي انتخاب واحد ) و همچنين نرم افزاهائي سازگار با Portal Device ها ( مثل موبايلهاي نه چندان جديدي كه وارد ايران هم شده اند يا PDA ها ) ميدهد . چه صفحه وب توليد كنيد چه رابط بانك اطلاعاتي براي يك كامپيوتر بزرگ ( Main Frame ) چه براي يك موبايل كوچك برنامه بنويسيد محيط و ابزار شما يكتاست .

قابليتهاي بسيار زياد و البته شگفت انگيز اين محيط چون سازگاري با Struts Framework و Controller checks in an XML resource file و Model View Controller و Remote View Manager و Presentation Model و plug-in to Macromedia’s Dreamweaver و ..و..و.. را با مراجعه به وب سايت Compuware و مطالعه توضيحات موجود خواهيد ديد . ( [ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

مهمان
01-07-2005, 08:02
سلام نستا جان
گير من دقيقا سر J2ME هست.
چون J2ME امکانات Java را ندارد و محدودتر هست.

مهمان
01-07-2005, 08:03
سلام
نستا جان اگر امکان داره منبع اين مقالاتي که گذاشتي را هم به من بده تا من کل مقاله هايي که مي نويسي را يکجا داشته باشم.
با تشکر

Nesta
01-07-2005, 08:11
سلام نستا جان
گير من دقيقا سر J2ME هست.
چون J2ME امکانات Java را ندارد و محدودتر هست.
سلام منبع یکی‌ نیست خیلی‌ هاش داره اگه توجه کنی‌ .چند تش هم مال خودم هست ولی‌ اکثرا زیرش یا بالاش سایت داره شما گیرتون j2me هست و چون برای موبایل استفاده می‌شه و java sdk هست.و اون جریانش خیلی‌ فرق داره با این بحث چون به موبایل هم بستگی‌ داره که bluetooth رو پشتیبانی‌ کنه و یا شاید حالا با سیدی و سیم به usb وصل بشه .و شما باید در قسمت موبایل تقاضا کنین چون خیلی‌ به موبایل بستگی‌ داره.و موبایل باید پشتیبانی‌ کنه.
و کمتر به جوا بستگی‌ داره.

مهمان
01-07-2005, 08:19
سلام نستا جان
J2ME يک زبان استاندارد براي موبايل مي باشد.
قسمت برنامه نويسي ارتباط با موبايل به bluetooth و infrared بستگي دارند.
ولي برنامه نويسي موبايل داراي استاندارد مي باشد و تفاوتي ندارد.
فقط يک چيز متفاوت هست و آن هم نوع گوشي مي باشد که سري 40 يا 60 يا 80 و ... باشد.
اين در واقع نسخه جاوا را مشخص مي کند که جاوا سري 40 باشد يا 60 و يا ...
با تشکر از راهنماييتون

Nesta
01-07-2005, 08:23
سلام نستا جان
J2ME يک زبان استاندارد براي موبايل مي باشد.
قسمت برنامه نويسي ارتباط با موبايل به bluetooth و infrared بستگي دارند.
ولي برنامه نويسي موبايل داراي استاندارد مي باشد و تفاوتي ندارد.
فقط يک چيز متفاوت هست و آن هم نوع گوشي مي باشد که سري 40 يا 60 يا 80 و ... باشد.
اين در واقع نسخه جاوا را مشخص مي کند که جاوا سري 40 باشد يا 60 و يا ...
با تشکر از راهنماييتون
سلام من یک سوال از شما دارم شما میخای ببینی‌ من بلدم یا میخای خودت یاد بگیری .
من اینرو نفهمیدم .چون شما که اطلاعات داری و میدونی‌ منم می‌دونم .فقط مقاله کم دارم راجبش.
حالا مشگل کجاست؟

مهمان
01-07-2005, 08:25
سلام نستا جان
من چيز زيادي نمي دونم
فقط مقاله درباره J2ME مي خواستم
حالا نمي دونم شما چه طوري فکر مي کنيد!!! :roll:

Nesta
01-07-2005, 08:28
سلام نستا جان
من چيز زيادي نمي دونم
فقط مقاله درباره J2ME مي خواستم
حالا نمي دونم شما چه طوري فکر مي کنيد!!! :roll:
سلام در مورد این که مقاله کم دارید خوب مقاله کم هست کلا چون چیز جدیدی هست قدیمی‌ که نیست .
باید بگردم و یا ترجمه کنم.
حالا من هم فهمیدم مشگل چی‌ بود .از اول میگفتی‌.
:wink:

مهمان
01-07-2005, 08:34
سلام نستا جان
يک سايت خوب پيدا کردم
ممنون از پستهايي که دادي
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]
بهتره اين سايت را يک جاي خوب معرفي کنيد
زحمتش گردن شما :mrgreen:

Nesta
01-07-2005, 08:38
سلام به نظرم در بخش موبایل خوب باشه چطور هست والا خودت زحمت رو کشیدی خودت هم معرفی‌ کن .من پیدا نکردم .کار خودت هست. :? 8)

مهمان
01-07-2005, 08:43
سلام
ولي فقط درباره برنامه نويسي موبايل نيست
پر ebook برنامه نويسي هست :mrgreen:

Nesta
01-07-2005, 08:51
سلام
ولي فقط درباره برنامه نويسي موبايل نيست
پر ebook برنامه نويسي هست :mrgreen:
سلام فعلا که برای موبایل به کار میگیرن و استفاده چندانی‌ نداره به نظرم .
معروف شدنش هم واسه همین هست .
پس تو بخش وب بگو چون نرم افزار که نیست بخوان دانلد کنن.
:?:

MaFia
08-07-2005, 03:45
تاپيك اصلاح شد
>SOBHANI_NJ

SKYWARD60
01-11-2006, 20:11
تاپيك اصلاح شد
>SOBHANI_NJ
با تشكر از زحمات nesta (آموزش جاوا)
لطفا اين موضوع را ادامه دهيد
و اگر امكان دارد در مورد سرولت و كار با بانك و نحوه فارسي ساز كردن برنامه هاي جاوا مطلب بگذاريد
در ضمن اگر امكان دارد لينك دانلود Apachi Tomcat را نيز بگذاريد
با سپاس

SKYWARD60
01-11-2006, 20:16
با تشكر از زحمات nesta (آموزش جاوا)
لطفا اين موضوع را ادامه دهيد
و اگر امكان دارد در مورد سرولت و كار با بانك و نحوه فارسي ساز كردن برنامه هاي جاوا مطلب بگذاريد
در ضمن اگر امكان دارد لينك دانلود Apachi Tomcat را نيز بگذاريد
با سپاس

SKYWARD60
01-11-2006, 20:19
با تشكر از زحمات nesta (آموزش جاوا)
لطفا اين موضوع را ادامه دهيد
و اگر امكان دارد در مورد سرولت و كار با بانك و نحوه فارسي ساز كردن برنامه هاي جاوا مطلب بگذاريد
در ضمن اگر امكان دارد لينك دانلود Apachi Tomcat را نيز بگذاريد
:rolleye: :question:
با سپاس

nasim1984
10-11-2006, 13:04
عالي بود من ميخوام در مورد اديتور هاي مختلف جاوا واين كه كد.مش بهتر هست بدونم.

m.active
22-02-2007, 19:26
دمت گرم نستا جان.
اگر كتاب ارژينالشو كسي خواست اسمشو بگه تا براش لينكشو بزارم.( فقط پي ام)