Download presentation
Presentation is loading. Please wait.
1
دکتر مظفر بگ محمدی دانشگاه ایلام
اجزاء سازنده دکتر مظفر بگ محمدی دانشگاه ایلام
2
ایجاد اشیاء اشیاء توسط عملگر new ایجاد می شوند:
Date myDate = new Date( ); عبارت: new Date( ) باعث فراخوانی متد خاصی به اسم جز سازنده می شود. سازنده ها جهت ساخت اشیاء و مقدار دهی اولیه متغییرهای کلاس استفاده می شوند.
3
سازنده یک سازنده: هم اسم کلاسی است که توسط سازنده ساخته می گردد. دارای مقدار بازگشتی نیست. (حتی void) اگر پیاده کننده ی کلاس سازنده را تعریف نکند، کامپایلر جاوا بصورت اتوماتیک یک سازنده ی بدون پارامتر برای کلاس تعریف می کند. اغلب ما سازنده ها را دوباره بارگذاری می کنیم. خوب است که همیشه یک جزء سازنده ی بدون پارامتر در کلاس داشته باشیم.
4
نسخه ی تقریباً نهایی کلاس Date
public class Date { private String month; private int day; // private int year; //4 digits // no-argument constructor // implementer chooses the default month, day, year public Date( ) { month = “January”; day = 1; year = 2007; // or better yet, call setDate(1, 1, 2007); } // alternative constructor public Date( int month, int day, int year ) { this.month = monthString(month) this.day = day; this.year = year; (continued)
5
Date Class (cont’d) // another alternative constructor // January 1 of the specified year public Date( int newYear ) { this.month = monthString( 1 ) this.day = 1; this.year = newYear; } // a constructor which makes a copy of an existing Date object // discussed in more detail later public Date( Date otherDate ) { month = otherDate.month; day = otherDate.day; year = otherDate.year; } // remaining Date methods such as setDate, accessors, mutators // equals, toString, and stringMonth } // end of Date class
6
استفاده از سازنده ی کلاس Date
public class DateDemo { public static void main( String[ ] args) { Date birthday = new Date( 1, 23, 1982 ); String s1 = birthday.toString( ); // January 23, 1982 System.out.println( s1 ); Date newYears = new Date( 2009 ); String s2 = newYears.toString( ); // January 1, 2009 System.out.println( s2 ); Date holiday = new Date( birthday ); String s3 = holiday.toString( ); // January 23, 1982 System.out.println( s3 ); Date defaultDate = new Date( ); String s4 = defaultDate.toString( ); // January 1, 2007 System.out.println( s4 ); }
7
سازنده یthis( ) اگر چندین سازنده برای کلاس بنویسیم، می توانیم داخل یک سازنده ی کلاس سازنده ی دیگری را فراخوانی کنیم. سازنده ی فراخوانی شده this( ) نام دارد.
8
سازنده های بهتر Date // no-argument constructor
// implementer chooses the default month, day, year public Date( ) { this( 1, 1, 2007 ); } // alternative constructor // January 1 of the specified year public Date( int newYear ) { this ( 1, 1, newYear ); } // most general alternative constructor called by other // constructors public Date( int month, int day, int year ) { this.month = monthString(month) this.day = day; this.year = year;
9
در حافظه چه اتفاقی می افتد: پشته و توده
هنگام اجرای برنامه، متغییرهای محلی در محلی از حافظه به اسم پشته دخیره می شوند. می توان از یک جدول برای توصیف متغییرهای ذخیره شده در پشته استفاده کرد: Var Value x y بقیه ی حافظه تحت عنوان توده شناخته می شود و برای تخصیص های دینامیک استفاده می شود.
10
حافظه ی اصلی پشته بر حسب نیاز رشد می کند یا کوچک می شود. توده هم چنین وضعیتی دارد. قسمتی از حافظه بین توده و پشته بدون استفاده (آزاد ) است. Stack Unused Memory Heap
11
کد زیر که دو شی Date ایجاد می کند را در نظر بگیرید: Date d1, d2;
ایجاد شی کد زیر که دو شی Date ایجاد می کند را در نظر بگیرید: Date d1, d2; d1 = new Date(1, 1, 2000); d2 = new Date(7, 4, 1776); این متغییرها و اشیاء در کجای حافظه ذخیره می شوند؟ چرا این موضوع برای ما مهم است؟
12
اشیاء در حافظه d1 = new Date(1, 1, 2000); دستور: Date d1, d2;
دو متغییر محلی در پشته ایجاد می کند. دستورات: d1 = new Date(1, 1, 2000); d2 = new Date(7, 4, 1776); اشیاء را در توده ایجاد می کنند. d1 و d2 دارای آدرس این اشیاء در حافظه هستند (مطابق شکل زیر) به d1 و d2 متغییرهای مرجع می گوییم. متغییرهای مرجعی که به جایی از حافظه منتسب نشده اند دارای مقدار null هستند. d1 d2 Stack Heap January 1 2000 July 4 1776
13
اهمیت موضوع (1) d1 d2 Stack Heap January 1 2000 July 4 1776
کد زیر را در نظر بگیرید: Date d1, d2; d1 = new Date(1, 1, 2000); d2 = new Date(7, 4, 1776); حال حافظه بصورت روبرو تغییر می کند. دستور d1==d2 را در نظر بگیرید. به یاد آورید که محتوی d1 و d2 برابر آدرس اشیائی از نوع Date است. چون که اشیاء Date در توده قرار دارند و دارای آدرس متفاوتی هستند، نتیجه دستور d1==d2 غلط است و تساوی دو شی را چک نمی کند. بلکه تنها اگر d1 و d2 به یک شی اشاره کنند، دستور فوق مقدار صحیح بر می گرداند. پس برای چک کردن تساوی دو شی چکار کنیم؟ کلاس Date باید متدی به اسم equals (یا هر اسم مناسب دیگر) داشته باشد که مقدار تمام متغییرهای دو کلاس را با هم مقایسه نماید. آن وقت برای چک کردن تساوی d1 و d2 می توانیم بنویسیم: d1.equals( d2 );
14
اهمیت موضوع (2) Date d2 = new Date( d1 );
حال دستورات زیر و وضعیت حافظه را پس از اجرای آنها ببینید: Date d1 = new Date(1, 1, 2000); Date d2 = d1; Heap Stack January 1 2000 d1 d2 حال d1 و d2 به یک شی مشابه اشاره می کنند. به این موضوع اسم مستعار می گویند که اغلب بصورت غیر عمدی اتفاق می افتد و می تواند خطرناک باشد. چرا؟ اگر منظور شما این است که d2 نسخه ای از d1 باشد، کد زیر اینکار را بصورت صحیح انجام می دهد: Date d2 = new Date( d1 );
15
اهمیت موضوع (3) کد زیر و وضعیت حافظه را پس از اجرای آن ببینید: Date d1 = new Date(1, 1, 2000); // line 1 d1 = new Date(12, 25, 2007); // line 2 d1 Stack Heap January 1 2000 December 25 2007 After line 1 After line 2
16
اهمیت موضوع (4) جمع آوری آشغال
d1 Stack Heap January 1 2000 December 25 2007 جمع آوری آشغال همانطور که دیاگرام نشان می دهد پس از اجرای خط دوم، هیچ متغییری به محلی که شامل “January”, 1, 2000 است اشاره نمی کند. در C/C++ این موضوع به عنوان نشت حافظه شناخته می شود. در C/C++ این وظیفه ی برنامه نویس است که حافظه های تخصیص یافته ی دینامیک را به قسمت خالی توده برگرداند. جاوا یک جمع کننده ی آشغال پیش ساخته دارد. جاوا بصورت منظم اشیاء یتیم را پیدا کرده و حافظه ی اشغال شده توسط آنها را به قسمت خالی توده بر می گرداند.
17
آرایه ای از اشیاء می توان نوع پایه ی آرایه را از نوع کلاس در نظر گرفت.
دستور: Date[] holidayList = new Date[20]; 20 متغییر ارجاع ایجاد می کند که می توانند به اشیائی از نوع Date اشاره کنند. بر خلاف انتظار، این دستور 20 شی از نوع Date ایجاد نمی کند. متغییرهای فوق الذکر بصورت اتوماتیک دارای مقدار null هستند. هر گونه تلاشی برای ارجاع به آنها موجب تولید پیغام خطای null pointer exception خواهد شد. 17
18
متغییرهای پایه و مرجع هر متغییری دارای یک محل در حافظه است.
در مورد متغییرهای پایه، مقدار متغییر در محلی از حافظه که به متغییر تخصیص داده شده است ذخیره می گردد. یعنی متغییرهای پایه همیشه به مقدار مشخصی حافظه نیاز دارند. وقتی که متغییر از نوع کلاس باشد، فقط آدرس شی (آدرس ارجاع) در در محلی از حافظه که به متغییر تخصیص داده شده است ذخیره می گردد (در پشته). خود شی در توده قرار دارد. مثل متغییرهای پایه، اندازه ی حافظه ی متغییر مرجع در پشته ثابت است. اما، اندازه ی حافظه تخصیص داده به شی در توده می تواند هر مقداری باشد. 18
19
پارامترهای کلاس تمام پارامترهای جاوا از متد ارجاع با مقدار استفاده می کنند. یعنی پارامتر یک متغییر محلی است که مقدار آن با مقدار آرگومان یکی است. لذا تغییر مقدار پارامتر باعث تغییر مقدار آرگومان نمی شود. پارامتراهای که از نوع کلاس هستند، نسبت به پارامترهایی که از نوع پایه هستند رفتار متفاوتی دارند. آنها مثل زبانهایی عمل می کنند که از متد ارجاع با آدرس (مثل زبان C++) برای پارامترها پشتیبانی می کنند. 19
20
پارامترهای کلاس مقداری که در پارامتر از نوع کلاس قرار داده می شود یک آدرس ارجاع (آدرس شی در توده) است. یعنی پارامتر یک اسم دیگر برای آرگومان است. لذا هر گونه تغییر در شی مورد ارجاع پارامتر باعث تغییر شی مورد ارجاع توسط آرگومان می گردد. چون هر دو به یک شی اشاره می کنند. اما تغییر خود پارامتر تاثیری روی آرگومان ندارد و فقط باعث می شود پارامتر به جای دیگری اشاره کند. 20
21
مثال public class DateParameterTest { public static void changeDay (int day) { day = 1; } public static void changeDate1( Date aDate ) { aDate = new Date( 1, 1, 2001); } public static void changeDate2( Date aDate ) { aDate.setDate( 1, 1, 2001 ); } public static void main( String[ ] args ) { Date birthday = new Date( 1, 23, 1982 ); changeDay( birthday.getDay( ) ); System.out.println(birthday.toString( )); // output? changeDate1( birthday ); System.out.println(birthday.toString( )); // output? changeDate2( birthday ); }
22
استفاده از = و == با متغییرهای کلاس
عملگر انتساب (=) دو متغییر ارجاع تولید می کند که به شی یکسانی اشاره دارند. عملگر تساوی (==) نیز در متغییرهای کلاس رفتار متفاوتی دارد. این عملگر تساوی متغییرهایی که به اشیا اشاره می کنند را چک می کند. یعنی مقدار آن در صورتی صحیح است که هر دو متغییر به یک مکان از حافظه رجوع کنند. اما تساوی مقادیر متغییرهای خصوصی دو کلاس را چک نمی کند. لذا، اگر دو شی با مقادیر خصوصی یکسان در دو محل مختلف از حافظه باشند، این عملگر مقدار غلط بر می گرداند. 22
23
مقدار null null یک ثابت است که می توان آنرا به متغییر ارجاع هر کلاسی نسبت داد. YourClass yourObject = null; به این معنا که متغییر ارجاع مورد نظر دارای مقدار واقعی نیست. در جزء سازنده برای مقدار دهی اولیه متغییرهای کلاس کاربرد دارد. null یک شی نیست. بلکه برای متغییر ارجاعی که به هیچ مکانی از حافظه اشاره نمی کند، مثل یک مکان عمل می کند. چون که عملکرد null مثل آدرسهای حافظه است، می توان از عملگرهای == و != برای آزمایش این موضوع که آیا متغییر ارجاع به جایی اشاره دارد یا نه، استفاده کرد: if (yourObject == null) 23
24
اشیاء ناشناس به خاطر بیاورید که عملگر new باعث فراخوانی سازنده و ایجاد شی می شود. آدرس مکانی از حافظه که شی در آن ایجاد شده است را بر می گرداند. این آدرس را می توان به هر متغییری که از نوع کلاس شی ایجاد شده باشد نسبت داد. گاهی اوقات شی ایجاد شده آرگومان یک متد است و بعد از آن دیگر استفاده نمی شود. در این حالت شی به هیچ متغییر ارجاعی نسبت داده نشده است. یعنی اسم ندارد. شی ناشناس شی است که به هیچ متغییر ارجاعی نسبت داده نشده باشد. 24
25
مثال شی ناشناس یک شی ناشناس بعنوان پارامتر به تابع ارسال شده است:
Date birthday = new Date( 1, 23, 1982 ); if (birthday.equals( new Date ( 1, 7, 2000 ) ) System.out.println( “Equal!” ); همان کار با یک شی دارای اسم(temp) انجام شده است: Date birthday = new Date( 1, 23, 1982 ); Date temp = new Date( 1, 7, 2000 ); if (birthday.equals( temp ) System.out.println( “Equal!” );
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.