جلسه شماره 28رایگان

Why are strings immutable in Java? | چرا رشته ها در جاوا تغییر ناپذیرند؟

00:18:28

توضیحات جلسه

🎥 این ویدیو قسمت بیست و هشتم از بوت‌کمپ رایگان جاواست. 🔒 چرا رشته‌ها در جاوا تغییرناپذیرند؟ (String Immutability) 📝 در این قسمت به یکی از ویژگی‌های مهم کلاس String در جاوا می‌پردازیم: تغییرناپذیری (Immutability 💡 بررسی می‌کنیم که تغییرناپذیری دقیقاً به چه معناست و چرا رشته‌ها در جاوا به‌صورت تغییرناپذیر طراحی شده‌اند. ⚙️ در ادامه یاد می‌گیریم: • مفهوم Immutable Object چیست • چرا کلاس String قابل تغییر نیست • این ویژگی چگونه باعث صرفه‌جویی در حافظه می‌شود • تغییرناپذیری چگونه امنیت و پایداری داده‌ها را افزایش می‌دهد 🔍 با بررسی نحوه کار رشته‌ها در String Pool و رفتار آن‌ها در حافظه، درک عمیق‌تری از طراحی داخلی جاوا به دست می‌آوریم. ✅ در پایان جلسه، همه نکات کلیدی را مرور می‌کنیم تا درک کاملی از **اهمیت و کاربرد تغییرناپذیری رشته‌ها در جاوا** داشته باشیم. 👥 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi ❓ هر سوالی داشتی می‌تونی در گروه بپرسی؛ من یا مربی‌های گروه کمکت می‌کنیم. 🚀 بوت‌کمپ رایگان جاوا – آموزش پروژه‌محور برای یادگیری عمیق و ورود به بازار کار.

جزوه و مستندات

مفاهیم کلیدی

  • 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 می‌توانند بدون نگرانی از تغییر هم‌زمان داده‌ها، از یک رشته مشترک استفاده کنند.