دادهی رشته (string) یکی از انواع دادهها در زبان برنامهنویسی جاوا است. رشته (String) دنبالهای از کاراکترها است. در جاوا اشیا کلاس string غیرقابل تغییر هستند. نوع داده string را پس از ایجاد نمیتوان تغییر داد. تمام دادههای string تعریف شده در برنامه در String Constant Pool ذخیره میشوند. در این مقاله با نحوه ذخیرهسازی دادههای string، نحوه کار String Constant Pool و فواید آن آشنا میشویم.
Java String Pool چیست؟
Java String Pool یک بخش از حافظه هیپ (heap) است. تمام رشتههای تعریف شده در برنامه در این بخش ذخیره میشوند. در ابتدا ماشین مجازی جاوا (JVM – Java Virtual Machine)، هنگام ایجاد یک رشته، وجود آن را در String Pool بررسی میکند. اگر آن رشته قبلاً در String Pool ذخیره شده باشد، متغیر جدید به همان شیء قبلی ارجاع داده میشود. اگر آن رشته وجود نداشته باشد، یک شیء جدید در String Pool ایجاد میشود.
برای آشنایی بیشتر با ماشین مجازی جاوا (JVM – Java Virtual Machine) میتوانید به مقاله « نحوه کار JVM » مراجعه کنید.
حافظه استک و هیپ
در ابتدا برای درک بهتر نحوهی کار Java String Pool بهتر است با مفاهیم حافظه استک و هیپ کمی آشنا شویم.
حافظه هیپ (Heap memory) بخشی از حافظه است که برای ذخیرهسازی دادهها به صورت دینامیک استفاده میشود. برخی ویژگیهای آن عبارتند از:
- برای دادههای پیچیده و با عمر نامشخص مناسب است.
- برنامهنویس در برخی زبانها مانند C++ مسئول تخصیص و آزادسازی حافظه است.
- دسترسی به دادهها نسبت به حافظه استک (Stack) کندتر است.
- البته در زبانهای مانند جاوا، آزادسازی حافظه به صورت خودکار انجام میشود.
حافظه استک (Stack memory) بخشی از حافظه است که برای ذخیرهسازی دادهها به صورت موقتی و با دسترسی سریع استفاده میشود. برخی ویژگیهای آن عبارتند از:
- برای ذخیره متغیرهای محلی و پارامترهای توابع استفاده میشود.
- تخصیص و آزادسازی حافظه به صورت خودکار انجام میشود.
- دسترسی به دادهها سریعتر از حافظه هیپ است.
- عمر دادهها به مدت اجرای تابع یا بلوک کد محدود است.
یک مثال از Java String Pool
دو برنامهای که با زبان جاوا در مثال اول و دوم نوشتهشده است را در نظر بگیرید. در مثال اول خروجی Yes است ولی در مثال دوم خروجی No است. فکر میکنید دلیل این تفاوت چیست؟
مثال اول با خروجی Yes:
// Program 1: Comparing two references to objects
// created using literals.
import java.util.*;
// Driver Class
class GFG {
// main function
public static void main(String[] args)
{
String s1 = "abc";
String s2 = "abc";
// Note that this == compares whether
// s1 and s2 refer to same object or not
if (s1 == s2)
System.out.println("Yes");
else
System.out.println("No");
}
}
// Program 2: Comparing two references to objects
// created using new operator.
import java.util.*;
// Driver Class
class GFG {
// main function
public static void main(String[] args)
{
String s1 = new String("abc");
String s2 = new String("abc");
// Note that this == compares whether
// s1 and s2 refer to same object or not
if (s1 == s2)
System.out.println("Yes");
else
System.out.println("No");
}
}
نحوهی کار Java String Pool
یکی از مهمترین ویژگیهای رشته در جاوا غیرقابل تغییر بودن است. به عبارت دیگر، زمانی که یک رشته ایجاد میشود، وضعیت داخلی آن در طول اجرای برنامه ثابت باقی میماند. این غیرقابل تغییر بودن به کمک String Constant Pool که بخشی از حافظه هیپ است، امکانپذیر میشود. وقتی یک رشته در جاوا تعریف میشود، شیء نوع string (متغیر) در حافظه استک ساخته میشود در حالی که مقدار آن رشته در حافظهی هیپ ذخیره میشود. برای درک بهتر بیایید مقداری به یک رشته str1 اختصاص دهیم.
String str1 = "Hello";

شکل ۱.نحوهی تخصیص حافظه برای str1
حال متغیر str1 و str2 را که مقادیر یکسان دارند را در نظر بگیرید.
String str1 = "Hello";
String str2 = "Hello";

شکل ۲.نحوهی تخصیص حافظه برای str1 و str2
اگر یک شیء رشتهای مقدار جدیدی دریافت کند، مقدار جدید به عنوان یک نمونهی جداگانه در String Constant Pool ذخیره خواهد شد.
مثال زیر را در نظر بگیرید:
String str1 = "Hello";
String str2 = "Hello";
String str3 = "Class";
تصویر زیر، نحوهی تخصیص حافظه برای str1، str2 و str3 را نشان میدهد.

یکی از راههای جلوگیری از تخصیص حافظه در String Pool این است که هنگام ایجاد یک شیء رشتهای از کلمهی کلیدی new استفاده کنیم. کلمهی کلیدی new باعث میشود که همیشه یک نمونهی جدید ایجاد شود، صرفنظر از اینکه همان مقدار قبلاً استفاده شدهاست یا خیر. استفاده از new باعث میشود که نمونهی رشتهای در حافظه هیپ اما خارج از String Constant Pool ذخیره شود. این موضوع کاملاً منطقی است، زیرا در این روش مکانیزم کش (Cache) و استفادهی مجدد از نمونهها وجود ندارد.
برای مثال:
String str1 = new String("John");
String str2 = new String("Doe");
شکل ۴ نحوهی تخصیص حافظه برای str1 و str2 را نشان میدهد.

دلیل تفاوت نتیجه در مثال اول
حال بعد از آشنایی با String Constant Pool میتوان دلیل تفاوت در خروجی دو مثال ابتدای مقاله را توضیح داد.
مثال اول:
class GFG {
// main function
public static void main(String[] args)
{
String s1 = "abc";
String s2 = "abc";
// Note that this == compares whether
// s1 and s2 refer to same object or not
if (s1 == s2)
System.out.println("Yes");
else
System.out.println("No");
}
}
در مثال اول هر دو متغیر str1 و str2 به یک شیء در String Pool اشاره میکنند. به همین دلیل، عملگر == برای اینها true را برمیگرداند، چون هر دو به همان آدرس حافظه (شیء مشابه) اشاره میکنند.
مثال دوم:
import java.util.*;
// Driver Class
class GFG {
// main function
public static void main(String[] args)
{
String s1 = new String("abc");
String s2 = new String("abc");
// Note that this == compares whether
// s1 and s2 refer to same object or not
if (s1 == s2)
System.out.println("Yes");
else
System.out.println("No");
}
}
در این حالت str1 و str2 به دو شیء مختلف در حافظه اشاره میکنند، حتی اگر محتویات آنها (یعنی "abc") مشابه باشد. در نتیجه، str1 == str2 برابر با false خواهد بود، چون مراجع آنها متفاوت است.
نتیجهگیری
- String Constant Pool باعث کاهش مصرف حافظه و بهبود عملکرد میشود.
- اگر از کلمهی کلیدی new برای ایجاد String استفاده شود، شیء جدیدی در حافظهی هیپ ایجاد میشود، نه در String Pool.
- عملگر == فقط مراجع حافظه را مقایسه میکند، بنابراین مقدار true فقط زمانی برمیگردد که هر دو متغیر به یک آدرس حافظه اشاره کنند.
- String Constant Pool در جاوا باعث استفادهی مجدد از مقادیر مشابه و کاهش تعداد اشیای غیرضروری در حافظه میشود.
ورود و ثبت نام برای ارسال نظر وارد شوید