ورود

View Full Version : چرا string ها تغییر ناپذیر هستند؟



khajavi
یک شنبه 30 تیر 1387, 17:08 عصر
توی کتابی که دارم می خونم به یه علتی برای این موضوع بیان کرده که نفهمیدم من عین جملات کتاب را در ادامه میارم اگه کسی اطلاعاتی در این مورد داره ممنون میشم کمکم کنه: But immutable strings have one great advantage: the compiler can arrange that strings are shared. To understand how this works, think of the various strings as sitting in a common pool. String variables then point to locations in the pool. If you copy a string variable, both the original and the copy share the same characters. Overall, the designers of Java decided that the efficiency of sharing outweighs the ineffi- ciency of string editing by extracting substrings and concatenating. Look at your own programs; we suspect that most of the time, you don’t change strings—you just com- pare them. (There is one common exception—assembling strings from individual char- acters or shorter strings that come from the keyboard or a file. For these situations, Java provides a separate class that we describe in the section “Building Strings” on page 62.)

amirshiva
یک شنبه 30 تیر 1387, 22:36 عصر
دوست عزیز تو این متنی که شما آوردین جائی ننوشته که string ها تغییر ناپذیرند لطفا بگین منظورتون کدوم جمله هست

mazdadoost
یک شنبه 30 تیر 1387, 23:27 عصر
دوست عزیز :
به نظرم سوال بسیار خوبی هست . ببینید برای رسیدن به جواب بهتره به این نکات دقیت کنیم:
1-رشته ها تنها اشیای جاوا هستند که مقدار لیترال دارند:بین دو تا "" !
2-عملگر + و =+ براشون تحریف شده .
3-با اینکه شی هستند و به عنوان ref برای jvm تعریف میشند اما همونطور که گفتین مثل سایر اشیائ توانایی تغیر مستغیم درشون نیست و تمام متد هایی که که روی رشته های کلاس String کار میکنند به جای تغیر در خود شی(دسترسی به اشارگر مستقیم شی یا همون رفرنسش)یه شی String دیگه برمیگردونه!

حالا چرا اینطوره!جواب در کارایی بیشتر هست!
همونطور که میبینید کامپایلر به اصطلاح رشته ها رو پایدار و تغیر ناپذیر در فایل کلاس تولید میکنه تا به نحوی با آور هد سه خصوصیتی که در مورد رشته ها در اختیار برنامه قرار میگیره مقابله بشه .چرا فقط رشته ها؟چون استفاده بسیار زیادی ازشون شده!و در نهایت طراحان جاوا تصمیم گرفتن تا رشته ها رو کاملا تعریف شده به خورد ران تایم بدن تا jvm بتونه بدون اینکه به فکر این باشه که این شی (String)چطور باید کنترل شه و حیاتش به چه نحوه و چه کلاسی ازش مشتق شده یا هر چی خیلی راحت با پیشفرض ثابت بودن باش برخورد کنه!
در عوض هر وقت واقعا لازم باشه برنامه روی خود String پردازش کنه برنامه نویس کاملا مسئولانه میتونه از کلاس های StringBuilder و StringBuffer استفاده کنه که توانایی کار با خود رشته ها رو در اختیار میذارند.هر چند آورهدی خیلی کم نسبت به String های معمولی دارند ولی خوب میشه روی این مسئله حساب کرد که برنامه نویس واقعا به این ویژگی نیاز داشته ..
موفق باشید.

khajavi
دوشنبه 31 تیر 1387, 06:37 صبح
خیلی ممنون mazdadoost از توضیحاتت
اما کاش یک نگاه به اون متنی که نوشته بودم هم میکردی. تو این متن از sharing صحبت شده که متوجه نشدم چه ربطی داذه

mazdadoost
دوشنبه 31 تیر 1387, 09:35 صبح
دوست عزیز :
بنده اشاره کرده بودم.به افزایش کارایی.منتها با توجه به اینکه توضیح Sharing و Pooling به نظرم با توجه به سطح مطالعه شما و اینکه آنچنان بدرد نمیخوره خود داری کردم.
و اما Sharin و Pooling.
به این مثال نگاه کن:

String s = "hi " + "Mr. " + " " + "khajavi";
به نظر تون چه اتفاقی برای این رشته حین کامپایل و رانتایم میفته!گفتیم که رشته ها پایدار هستند.یه نکته دیگه اینکه جاوا در اصل با رشته ها به عنوان یه ارایه از char ها برخورد میکنه که اول و طولش رو میدونه!
حالا کامپایلر برای ساختن رشته s میاد و به چای اینکه اون سه تا رشته دیگه رو به عنوان سه شی رشته جداگانه در حین رانتایم در نظر بگیره و در شی چهارم s بذاره(این یعنی حافظه برای 4 شی و سیکل های ساعت cpu بیشتر برای پاکسازیشون توسط gc!) میاد و فضای باید کد رو حین کامپایل چیزی شبیه کد زیر میکنه :


String s = "hi Mr. khajavi";

و این در فایل کلاس منعکس میشه ونه رانتیام.در واقع این تکنیک به یه آرایه از رشته ها ی ترکیب شده اشاره داره که از h شروع میشه و به طول 15 به i خطم میشه.که از اشتراک فضای بایت کد برای اون سه تا رشته بدست اومده.و این نشون میده که کامپایلر چطور اول و آخر رشته ها رو به اشتراک میذاره تا با کم کردن حافظه مصرفی واسطه و از طرفی کم شدن کار gc کمک کنه.حالا راتنایم هم به جای جمع 4 تا رشته فقط با یه رشته به اسم s طرفه که اون هم به یه ارایه از char ه اشاره داره که توضیحاتشو گفتم!و این نشون میده که چه طور کل رشته های برنامه در چیزی شبیه یه استخر یا همون Pool شناورند .
حالا به این مثال نگاه کنید:


public String sayHi(String title, String name)
{
return "hi " + title + " " + name;
}

در این مثال کامپایلر نمیدون از قبل با چی طرفه و نمیتونه از تکنیکی که در بالا گفتیم استفاده کنه.به روش های مختلفی بنا بر اینکه از چه تکنیک بهینه سازی استفاده کرده باشه کد های مختلفی ممکنه تولید شه:

return (new StringBuffer( )).append("hi ").
append(title).append(" ").append(name).toString( );
خوب میبینید اینجا نشون میده رشته ها واقعان پادارند و کامپایلر در عمل برای تغیر شون حین رانتیم به این شکل(وقتی مقدار رشته قبل از رانتیم معلوم نباشه!)از پیاده سازی کلاس StringBuffer استفاده میکنه.که با توجه به ماهیت خود کلاس StringBuffer از تکنیک قبل بهینگیش کمی کمتره!
فکر میکنم تا همین جا هم خوب باشه و موضوع روشن شده باشه.
موفق باشید.

khajavi
سه شنبه 01 مرداد 1387, 03:29 صبح
خیلی زیبا و کامل بود
تشکر