آموزش برنامه نویسی جاوا: برنامه نویسی شی گرا , قسمت ۲

0

برنامه نویسی جاوا: برنامه نویسی شی گرا
برنامه نویسی جاوا: برنامه نویسی شی گرا

آموزش برنامه نویسی جاوا: برنامه نویسی شی گرا , قسمت ۲

مقدمه:خب دوستان در ادامه قسمت قبلی این آموزش ,  حالا می‌خواهیم یک متد را در کلاس GradeBook بنویسیم. بنابراین ابتدا یک توضیحات (Comment) برای متد خود می‌نویسیم. کد زیر:

public class GradeBook 
	// display a welcome message to the GradeBook

حالا می‌خواهیم متدی با نام displayMessage ایجاد کنیم. کد زیر:

public class GradeBook 
	// display a welcome message to the GradeBook
	public void displayMessage() 
		System.out.println("Welcome to the GradeBook!");
	 // end method displayMessage
 // end class GradeBook

توضیحات در مورد متد فوق: سطح دسترسی متدی که ما در بالا تعریف کرده‌ایم، عمومی یا public است. (با سطوح دسترسی در جاوا در ادامه‌ی همین آموزش‌های شی گرایی آشنا می‌شوید). بعد از آن باید نوع برگشتی متد را مشخص کنیم. در اینجا نوع برگشتی متد ما void است یعنی متد ما هیج مقداری را بر نمی‌گرداند. بعد از آن هم نام متد را نوشته‌ایم و بعد هم آکولاد‌های باز و بسته قرار داده‌ایم تا بدنه‌ی متد مشخص شود. همانطور که مشاهده می‌کنید در بدنه‌ی متد کد خاصی نوشته نشده است. فقط با اجرای متد displayMessage پیغامی بر روی خروجی استاندارد چاپ می‌شود. همچنین دوباره با استفاده از کامنت‌ها، آخر متد و آخر کلاس را مشخص کرده‌ایم.

حالا ما اگر برنامه را اجرا کنیم هیچ خروجی‌ای در کنسول مشاهده نمی‌کنیم. علت چیست!؟ دلیل آن این است که نقطه‌ی شروع برنامه‌های جاوا متد main است و در حال حاضر متد main ما خالی از هرگونه کد است. پس بنابراین به سراغ کلاس اصلی که در آن متد main پیاده‌سازی شده است می‌رویم.

همانطور که در توضیحات در مورد شی گرایی گفته شد، تا وقتی که از روی یک کلاس، شی‌ای ساخته نشود، آن کلاس هیچ ارزشی ندارد و به هیچ دردی نمی‌خورد. همانطور که مشاهده کردید، برنامه را اجرا کردیم، اما هیچ خروجی‌ای دریافت نکردیم. پس بنابراین برای اینکه بتوانیم از کلاس GradeBook و متدی که در آن پیاده‌سازی شده است استفاده کنیم، باید از روی کلاس GradeBook یک شی یا یک آبجکت ایجاد کنیم تا با استفاده از آن آبجکت به متد موجود در کلاس GradeBook دسترسی پیدا کنیم.

همانطور که می‌دانید ما در جاوا هنگامی که می‌خواهیم یک متغیر تعریف کنیم، به صورت زیر این کار را انجام می‌دهیم:

int number;

یعنی ابتدا نوع متغیری که می‌خواهیم ایجاد کنیم را می‌نویسیم و بعد یک نام برای آن در نظر می‌گیریم. برای ساختن آبجکت هم دقیقا باید به همین شکل رفتار کنیم. در حقیقت ما باز هم می‌خواهیم یک متغیر تعریف کنیم. اما این بار متغیر ما از جنس داده‌های اولیه (Primitive Data Type) ها نیست، از جنس کلاس است (کلاس GradeBook). بنابراین ابتدا نام کلاس را می‌نویسیم و بعد هم یک نام برای آن در نظر می‌گیریم (این عملیات باید داخل متد main نوشته شود). به صورت زیر:

public class Main 

	public static void main(String[] args) 
		// Object Creation
		GradeBook book;
	

در کد بالا همانطور که مشاهده می‌کنید ما یک آبجکت تعریف کرده‌ایم، اما هنوز ایجاد نکرده‌ایم. در جاوا برای ایجاد و ساختن یک شی باید از کلمه‌ی کلیدی new استفاده کنیم. به کد تکمیل شده در زیر توجه کنید:

public class Main 

	public static void main(String[] args) 
		// Object Creation
		GradeBook book = new GradeBook();
	

در کد بالا بعد از نام آبجکت (book) علامت مساوی (Assignment) قرار داده‌ایم. سپس اُپراتور new را نوشته (که با این کار یک شی ایجاد می‌شود) و بعد نام کلاس را دوباره می‌نویسیم و یک پرانتز باز و بسته در جلوی آن قرار می‌دهیم و در آخر هم علامت سمیکالن را می نویسیم.

تا اینجای کار ما یک آبجکت از روی کلاس GradeBook ساخته‌ایم. حالا می‌خواهیم با استفاده از آبجکتی که ایجاد کرده‌ایم، به متد موجود در کلاس GradeBook دسترسی پیدا کنیم. برای این کار ابتدا نام آبجکت را می‌نویسیم (book)، سپس یک نقطه (.) قرار می‌دهیم و بعد نام متد مورد نظر را که در اینجا displayMessage است را می‌نویسیم. کد زیر:

public class Main 

	public static void main(String[] args) 
		// Object Creation
		GradeBook book = new GradeBook();
		book.displayMessage();
	

حالا اگر برنامه را اجرا کنید در خروجی استاندارد متن !Welcome to the GradeBook را مشاهده می‌کنید.

بخش‌های حافظه

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

نکته: حافظه در برنامه‌های جاوا به دو بخش تقسیم می‌شود. حافظه‌ی Stack و حافظه‌ی Heap. هنگامی که با استفاده از اُپراتور new یک آبجکتی ایجاد می‌کنیم، این آبجکت ما در بخشی از حافظه به نام Heap ذخیره می‌شود. در حقیقت book یک آبجکت (شی) نیست!، بلکه یک ارجاعی است به شی ساخته شده در حافظه‌ی Heap. (درست است که همه می گویند با استفاده از آبجکت مثلا book به فیلد‌ها و متد‌های یک کلاس می‌توانیم دسترسی داشته باشیم، اما book آبجکت نیست. این طرز بیان فقط برای راحت تلفظ کردن است. اگر بخواهیم درست بیان کنیم باید بگوییم با استفاده از متغیر book که در حافظه‌ی Stack ایجاد شده است، می‌توانیم به به شی‌ای که در Heap ساخته شده است اشاره کنیم.). به تصویر زیر توجه کنید:

برنامه نویسی جاوا: برنامه نویسی شی گرا
برنامه نویسی جاوا: برنامه نویسی شی گرا

در تصویر فوق در حافظه‌ی استک، ما یک متغیری داریم با نام parent که اشاره می‌کند به یک شی ساخته شده در حافظه‌ی هیپ. در کدی که ما نوشتیم متغیر book در حافظه‌ی استک (Stack) قرار می‌گیرد و ما با استفاده از این متغیر می‌توانیم به شی‌ای که در حافظه‌ی Heap ایجاد شده است، دسترسی پیدا کنیم.

نکته: متغیر‌های محلی هر متد روی استک قرار می‌گیرند، همانند book که یک متغیر محلی است، از جنس کلاس GradeBook که به شی‌ای در هیپ اشاره می‌کند.

Garbage Collector یا زباله روب

همانطور که ما آبجکت ایجاد می‌کنیم و آن آبجکت‌ها یا اشیا بر روی حافظه‌ی Heap قرار می‌گیرند، همانطور هم باید آن آبجکت‌ها را از روی حافظه‌ی Heap پاک کنیم. آزاد سازی حافظه توسط برنامه نویس فرآیندی پرخطا و پیچیده است. زیرا ممکن است برنامه نویس بخشی از حافظه که تخصیص داده شده است را delete نکند و با نشت حافظه (Memory Leak) مواجه شود و یا اینکه ممکن است به اشتباه شی‌ای را پاک کند. این مسئله در برنامه‌های بزرگ و پیچیده‌تر، سخت‌تر می‌شود، زیرا تعداد آبجکت‌ها افزایش پیدا می‌کند، بنابراین اشیا با یکدیگر ارجاعات متعددی دارند.

نشتی حافظه به علت عدم مدیریت صحیح در تخصیص حافظه‌ها و آزاد سازی آن‌ها رخ می‌دهد.

Garbage Collector یا زوباله روب بخشی از JVM است که وظیفه‌ی پاک کردن حافظه‌ی Heap را بر عهده دارد. وجود Garbage Collector در جاوا یک موهبت الهی برای برنامه نویسان جاوا است.

برنامه نویسی جاوا: برنامه نویسی شی گرا
برنامه نویسی جاوا: برنامه نویسی شی گرا

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

نکته‌ای که باید به آن توجه کنیم این است که متغیر‌های محلی هر متد بر روی حافظه‌ی Stack قرار می‌گیرند و بعد از پایان اجرای متد، تمام آن متغیر‌هایی که توسط آن متد بر روی حافظه‌ی استک ذخیره شده‌اند پاک می‌شوند. نکته این است که این کار اصلا نیازی به زباله روبی (GC) ندارد و تمام زبان‌های برنامه نویسی‌ای که متد و یا تابع دارند (مثل سی پلاس پلاس) این کار انجام می‌شود. به کد زیر دقت کنید:

public class Main 

	public static void show() 
		int number = 20;
		System.out.println(number);
	

	public static void main(String[] args) 
		System.out.println(number);
	

در کلاس بالا ما دو متد داریم. یکی متد main است و دیگری متد show. ما در متد show متغیری از جنس عدد صحیح با مقدار ۲۰ تعریف کرده‌ایم و سپس آن را در خروجی استاندارد نمایش داده‌ایم. حالا در داخل متد main ما باز هم می‌خواهیم مقدار متغیر number را نمایش دهیم، اما با خطای کامپایل مواجه می‌شویم. زیرا وقتی متد show شروع می‌شود، برای متغیر number در Stack حافظه‌ای اختصاص داده می‌شود و وقتی هم که متد به پایان می‌رسد، به صورت خودکار حافظه‌ی اختصاص داده شده از روی استک پاک می‌شود. بنابراین ما نمی‌توانیم از متغیر number در متد main استفاده کنیم. این کار در زبان‌هایی مانند ++C که Garbage Collector ندارد، دقیقا به همین صورت اتفاق می‌افتد. بنابراین نتیجه‌ای که می‌گیریم این است که GC فقط حافظه‌ی Heap را پاک می‌کند.

تنظیم کردن اندازه‌ی حافظه‌های Heap و Stack

می‌خواهیم برنامه‌ای بنویسیم که در آن اندازه‌ی حافظه‌های Heap و Stack را به طور دستی مشخص کنیم. یعنی ما می‌خواهیم اندازه‌ی این دو حافظه را دستکاری کنیم و برنامه‌ای بنویسیم که با اجرای آن‌ها برنامه با کمبود حافظه مواجه شود و کرش کند و دوباره به صورت دستی انداره‌ی حافظه‌ها را افزایش دهیم تا برنامه بدون مشکل اجرا شود.

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

معنیآرگومان
اندازه‌ی اولیه HeapXms-
حداکثر اندازه‌ی HeapXmx-
حداکثر اندازه‌ی StackXss-

نکته: با استفاده از آرگومان Xms- می‌توان اندازه‌ی اولیه‌ی حافظه‌ی Heap را مشخص کرد. همچنین توسط Xmx- می‌توان حداکثر اندازه‌ی حافظه‌ی هیپ را مشخص کرد و با Xss- هم حداکثر اندازه‌ی Stack.

مثال

ابتدا محیط توسعه‌ی اکلیپس را اجرا کنید و از منوی Run گزینه‌ی Run Configurations را انتخاب کنید. تصویر زیر:

بعد از انتخاب گزینه‌ی مورد نظر وارد پنجره‌ی زیر می‌شوید:

برنامه نویسی جاوا: برنامه نویسی شی گرا
برنامه نویسی جاوا: برنامه نویسی شی گرا

همانطور که در تصویر با یک فلش سبز رنگ مشخص شده است، تب Arguments را انتخاب کنید. سپس در قسمت VM Arguments یا همان آرگومان‌های ماشین مجازی، عبارت مشخص شده را بنویسید: Xmx-500m. در اینجا ما حداکثر اندازه‌ی حافظه‌ی Heap را برابر با ۵۰۰ مگابایت در نظر گرفته‌ایم. بر روی دکمه‌ی Run کلیک کنید (البته چیزی اجرا نمی‌شود، زیرا هنوز برنامه‌ای ننوشته‌ایم).

حالا کلاس اصلی برنامه را باز کرده و کد زیر را در آن بنویسید:

public class Main 

	public static void main(String[] args) 
		int[] numArray = new int[100000000];
	

در اینجا ما یک آرایه‌ای با طول ۱۰۰ میلیون ایجاد کرده‌ایم.

نکته: در اینجا می‌توانیم از یکی از قابلیت‌های جاوا ۸ استفاده کنیم. همانطور که در ریاضیات ما اعداد را سه تا سه تا جدا می‌کنیم، در جاوا ۸ هم با استفاده از Underscore (_) می‌توانیم اعداد را سه تا سه تا جدا کنیم. به صورت زیر:

public class Main 

	public static void main(String[] args) 
		int[] numArray = new int[100_000_000];
	

حالا برنامه را اجرا کنید. با اجرای این برنامه با ارور: OutOfMemoryError: Java heap space مواجه می‌شوید. اما راه حل چیست؟ ما قبل از اجرای برنامه، حداکثر اندازه‌ی حافظه‌ی Heap را مشخص کردیم. اما این حافظه برای اجرای چنین برنامه‌ای کافی نیست. بنابراین دوباره به پنجره‌ی Run Configurations مراجعه کرده و حداکثر اندازه‌ی حافظه را برابر با ۱۰۲۴m و یا یک گیگ قرار دهید و سپس برنامه را اجرا کنید. با افزایش حافظه دیگر برنامه‌ی ما کرش نمی‌کند.

حالا می‌خواهیم برنامه‌ای بنویسیم که حافظه‌ی Stack را پر کند و سر ریز شود. اصطلاحا StackOverflow گفته می‌شود و با خطای StackOverflowError مواجه می‌شویم. یکی از ساده‌ترین برنامه‌هایی که می‌توان نوشت تا استک سر ریز شود، استفاده از متد‌های بازگشتی (Recursive) است. به کد زیر توجه کنید:

public class Main 

	public static void main(String[] args) 
		System.out.println(function(1));
	

	static int function(int i) 
		if (i < 100000) 
			return function(i + 1);
		 else 
			return 0;
		
	

 نتیجه گیری: کاربران محترم به پایان مطلب برنامه نویسی جاوا: برنامه نویسی شی گرا رسیدیم, ما هنوز به مبحث بازگشتی نرسیده‌ایم، اما کدی که در بالا نوشته‌ایم به این صورت است که داخل کلاس Main یک متدی با نام function تعریف کرده‌ایم که یک پارامتر به عنوان ورودی دریافت می‌کند. در داخل متد function ما یک عبارت شرطی‌ای قرار داده‌ایم که تا زمانی که مقدار متغیر i کوچکتر از ۱۰۰۰۰۰ است، بلاک if اجرا شود. که در داخل بلاک if دوباره خود متد function فراخوانی می‌شود که یک مقدار به به پارامترش اضافه می‌کند. در اینجا برنامه همانند یک حلقه اجرا می‌شود، تا زمانی که متغیر i کوچکتر از ۱۰۰۰۰۰ شود. بعد از آن بلاک else اجرا می‌شود. حالا اگر برنامه را با همین وضعیت فعلی اجرا کنید، برنامه کرش می‌کند. زیرا حافظه‌ی Stack پر می‌شود. اما می‌توانیم با استفاده از آرگومان Xss- اندازه‌ی حافظه‌ی Stack را افزایش دهیم. برای این کار دقیقا مانند قبل به پنجره‌ی Run Configurations بروید و این بار این را بنویسید: Xss5m- . حالا اگر برنامه را اجرا کنیم، دیگر خطایی دریافت نمی‌کنیم و مقدار صفر (۰) در خروجی استاندارد چاپ می‌شود. علت درست اجرا شدن برنامه این است که برنامه حافظه‌ی کافی را در اختیار دارد، بنابراین بلاک دستور if کامل اجرا می‌شود و در آخر هم وقتی شرط حلقه نقض می‌شود، بلاک else اجرا می‌شود و مقدار صفر را بر می‌گرداند. همراه با پردیس سلامت باشید.

گردآوری:پردیس سلامت

منبع:zoomit

لینک مطلب

پاسخ دهید