Why are strings immutable in Java? | چرا رشته ها در جاوا تغییر ناپذیرند؟
توضیحات جلسه
جزوه و مستندات
مفاهیم کلیدی
- Immutable
به اشیایی گفته میشود که پس از ایجاد در حافظه، وضعیت یا مقدار آنها قابل تغییر نیست.
در جاوا، کلاس String بهصورت Immutable طراحی شده است.
- String Pool
String Pool ناحیهای اختصاصی در حافظه Heap است که جاوا رشتههای ایجادشده را در آن ذخیره میکند.
اگر رشتهای با مقدار مشابه قبلاً در این ناحیه وجود داشته باشد، جاوا بهجای ایجاد یک شیء جدید، از همان نمونه قبلی استفاده میکند.
- Reference
Reference متغیری است که به یک شیء در حافظه اشاره میکند.
در رشتهها، تغییر مقدار متغیر به معنای تغییر رفرنس آن و اشاره به یک شیء جدید است؛ نه تغییر محتوای شیء قبلی.
نکات مهم مصاحبهای
- چرا
Stringدر جاوا تغییرناپذیر (Immutable) است؟
مهمترین دلایل تغییرناپذیر بودن String، صرفهجویی در مصرف حافظه از طریق String Pool و افزایش امنیت است.
تغییرناپذیری از تغییر ناخواسته دادهها هنگام استفاده در متدها و Threadهای مختلف جلوگیری میکند.
- تفاوت تعریف رشته بهصورت
Literalبا استفاده از کلمه کلیدیnewچیست؟
وقتی رشته بهصورت Literal، مانند "test"، تعریف شود، در String Pool قرار میگیرد.
اما استفاده از new String() یک شیء جدید خارج از String Pool ایجاد میکند و میتواند باعث مصرف غیرضروری حافظه شود.
- در صورت الحاق (
Concatenation) مداوم رشتهها در یک حلقه، چه اتفاقی برای حافظه میافتد؟
بهدلیل Immutable بودن String، در هر بار تغییر یک شیء جدید در حافظه ایجاد میشود.
این کار باعث ایجاد اشیای موقت فراوان و درگیر شدن مداوم Garbage Collector میشود و در نتیجه، عملکرد برنامه کاهش مییابد.
- چرا استفاده از
Stringدر حلقههای طولانی توصیه نمیشود؟
زیرا در هر تکرار، یک شیء جدید ساخته میشود و حافظه بیشتری اشغال میکند؛ در نتیجه، عملکرد سیستم کاهش مییابد.
برای عملیات متعدد الحاق رشتهها، استفاده از StringBuilder انتخاب مناسبتری است.
- عملگر
==در مقایسه دو رشته چه چیزی را بررسی میکند؟
عملگر == رفرنس، یا همان آدرس شیء در حافظه، را مقایسه میکند؛ نه محتوای دو رشته را.
اگر دو رشته به یک نمونه موجود در String Pool اشاره کنند، نتیجه میتواند true باشد. اما اگر یکی از رشتهها با new String() ایجاد شده باشد، ممکن است نتیجه false شود؛ حتی اگر محتوای دو رشته یکسان باشد.
- نقش امنیت در تغییرناپذیری رشتهها چیست؟
رشتهها در بسیاری از موقعیتهای حساس، مانند نام کاربری، رمز عبور و آدرس شبکه، استفاده میشوند.
تغییرناپذیری آنها از تغییرات ناخواسته داده در زمان اجرای برنامه جلوگیری میکند و باعث میشود مقدار رشته پس از اعتبارسنجی، بدون تغییر باقی بماند.
مثال یا سناریوی کاربردی
سناریوی امنیت در تراکنش بانکی
فرض کنید متدی برای واریز وجه دارید که نام صاحب حساب را بهصورت String دریافت میکند.
ابتدا برنامه نام را اعتبارسنجی میکند؛ برای مثال، بررسی میکند که حسابی با نام «فرزاد» وجود دارد یا خیر.
اگر رشتهها قابلتغییر (Mutable) بودند، ممکن بود در فاصله زمانی میان تأیید نام و انجام عملیات واریز، مقدار رشته در بخش دیگری از برنامه به «علی» تغییر کند.
در این حالت، تأییدیه برای «فرزاد» صادر شده است؛ اما پول به حساب «علی» واریز میشود.
تغییرناپذیری String تضمین میکند که داده پس از تأیید، بدون تغییر باقی بماند.
بیشتر بدانید
- IDE Tip
در محیط IntelliJ IDEA، اگر برای تعریف یک رشته ساده از new String() استفاده کنید، محیط توسعه به شما هشدار (Warning) میدهد.
این هشدار نشان میدهد که استفاده از new String() در این حالت اضافی است و بهتر است رشته را بهصورت Literal تعریف کنید تا از مزایای String Pool بهرهمند شوید.
- نکته سینتکسی
برای مقایسه محتوای دو رشته، بهجای آدرس حافظه، همیشه از متد equals() استفاده کنید.
عملگر == فقط رفرنسها را مقایسه میکند و در صورت استفاده از new String() ممکن است نتیجه غیرمنتظرهای داشته باشد.
- بهینهسازی
تغییرناپذیری باعث میشود رشتهها بهصورت پیشفرض Thread-Safe باشند.
در نتیجه، چندین Thread میتوانند بدون نگرانی از تغییر همزمان دادهها، از یک رشته مشترک استفاده کنند.
