اصل: ایجاد رشته جاوا با استفاده از " " یا سازنده؟ توسط X Wang در جاوا، یک رشته را می توان با استفاده از دو روش ایجاد کرد:
String x = "abc";
String y = new String("abc");
تفاوت بین استفاده از دو کوتیشن و استفاده از سازنده چیست؟
1. دو نقل قول در مقابل. سازنده
با نگاهی به دو مثال ساده می توان به این سوال پاسخ داد. مثال 1:String a = "abcd";
String b = "abcd";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // True
a==b
درست است زیرا a
هر دو b
به یک شی ارجاع میدهند - رشتهای که بهعنوان تحت اللفظی (رشته تحت اللفظی در زیر) در ناحیه روش اعلام شده است (ما خواننده را به منبع منبع خود ارجاع میدهیم: 8 نمودار برتر برای درک جاوا ، نمودار 8). هنگامی که همان رشته تحت اللفظی بیش از یک بار ایجاد می شود، تنها یک کپی از رشته در حافظه ذخیره می شود، فقط یک نمونه از آن (در مورد ما "abcd"). به این "تطبیق رشته" می گویند. تمام ثابت های رشته ای که در زمان کامپایل پردازش می شوند به طور خودکار در جاوا درون می شوند. مثال 2:
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d); // False
System.out.println(c.equals(d)); // True
c==d
false زیرا به دو شی متفاوت در حافظه (روی پشته) اشاره می کنند c
. d
اشیاء مختلف همیشه ارجاعات متفاوتی دارند. این نمودار دو وضعیتی که در بالا توضیح داده شد را نشان می دهد:
2. رشته های درونی در مرحله اجرای برنامه
نویسنده از LukasEder تشکر میکند (نظر زیر متعلق به اوست): درونسازی رشته نیز میتواند در حین اجرای برنامه رخ دهد، حتی اگر دو رشته با استفاده از سازنده ایجاد شوند:String c = new String("abcd").intern();
String d = new String("abcd").intern();
System.out.println(c == d); // Now true
System.out.println(c.equals(d)); // True
3. چه زمانی از دو کوتیشن و چه زمانی از سازنده ها استفاده شود
با توجه به این واقعیت که "abcd" تحت اللفظی همیشه از نوع String است، استفاده از سازنده یک شی غیر ضروری اضافی ایجاد می کند. بنابراین اگر فقط نیاز به ایجاد یک رشته دارید باید از دو نقل قول استفاده کنید. اگر واقعاً نیاز به ایجاد یک شی جدید در پشته دارید، باید از سازنده استفاده کنید. موارد استفاده در اینجا نشان داده شده است (اصلی) . (من متن ترجمه شده را در زیر ارائه می کنم. اما همچنان به شما توصیه می کنم که با کد مفسران در این پیوند آشنا شوید.)متد substring() در JDK 6 و JDK 7
متد substring() در JDK 6 و JDK 7 توسط X Wang روشsubstring(int beginIndex, int endIndex)
در JDK 6 و JDK 7 متفاوت است. دانستن این تفاوت ها می تواند به شما در استفاده بهتر از این روش کمک کند. برای سهولت در خواندن، در زیر substring()
به معنای نحو کامل، یعنی. substring(int beginIndex, int endIndex)
.
1. substring () چه کاری انجام می دهد؟
این روشsubstring(int beginIndex, int endIndex)
رشتهای را برمیگرداند که با شماره کاراکتر شروع میشود beginIndex
و با شماره کاراکتر به پایان میرسد endIndex-1
.
String x = "abcdef";
x = x.substring(1,3);
System.out.println(x);
خروجی:
bc
2. وقتی substring() فراخوانی شود چه اتفاقی می افتد؟
ممکن است بدانید که به دلیل تغییر ناپذیری ،x
هنگام تخصیص x نتیجه به یک ردیف کاملاً جدید اشاره می کند (نمودار را ببینید): با این حال، این نمودار کاملاً صحیح نیست. این نشان نمی دهد که در واقع در پشته چه اتفاقی می افتد. آنچه در واقع هنگام فراخوانی اتفاق می افتد در JDK 6 و JDK 7 متفاوت است. x.substring(1,3)
x
substring()
3. substring() در JDK 6
نوع رشته توسط نوع آرایه پشتیبانی می شودchar
. در JDK 6، کلاس String
شامل 3 فیلد است: char value[]
, int offset
, int count
. آنها برای ذخیره آرایه واقعی کاراکترها، شاخص اولین کاراکتر در آرایه، تعداد کاراکترهای موجود در خط استفاده می شوند. هنگامی که متد فراخوانی می شود substring()
، یک ردیف جدید ایجاد می کند، اما مقدار متغیر همچنان به همان آرایه در پشته اشاره می کند. تفاوت بین دو رشته تعداد کاراکترها و مقدار شاخص کاراکتر شروع در آرایه است. کد زیر ساده شده است و فقط شامل اصول اولیه برای نشان دادن مشکل است.
//JDK 6
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
public String substring(int beginIndex, int endIndex) {
//check boundary
return new String(offset + beginIndex, endIndex - beginIndex, value);
}
4. مشکل ناشی از substring() در JDK 6
اگر یک رشته بسیار طولانی دارید، اما فقط به بخش کوچکی از آن نیاز دارید که هر بار با استفاده از آن به دست می آوریدsubstring()
. این باعث مشکلات اجرا می شود، زیرا شما فقط به یک بخش کوچک نیاز دارید، اما هنوز باید کل رشته را ذخیره کنید. برای JDK 6، راه حل کد زیر است که رشته را به یک زیررشته واقعی میفرستد:
x = x.substring(x, y) + ""
کاربر STepeR یک سوال را فرموله کرد (به نظر او مراجعه کنید) و اضافه کردن نکته 4 ضروری به نظر می رسید. "مشکل ایجاد شده substring()
در JDK 6" یک مثال گسترده تر است. امیدوارم این پاسخ باشد و به دیگران کمک کند تا به سرعت بفهمند مشکل چیست. این هم کد:
String a = "aLongLongString";
String b = a.substring(1, 2);
String c = a.substring(2, 6);
بنابراین، در JDK 7 b
، اشیایی с
از نوع a String
که با فراخوانی متدی substring()
روی یک شی از نوع a ایجاد میشوند String
، به دو آرایه جدید ایجاد شده در heap- L
for b
, ongL
for ارجاع خواهند داد c
. این دو آرایه جدید به همراه آرایه اصلی که با a ارجاع داده شده است در پشته ذخیره می شوند aLongLongString
. آن ها آرایه اصلی در هیچ کجا ناپدید نمی شود. حالا بیایید به JDK 6 برگردیم. در JDK 6، یک پشته حاوی یک آرایه واحد است aLongLongString
. پس از اجرای خطوط کد
String b = a.substring(1, 2);
String c = a.substring(2, 6);
اشیاء به همان آرایه در پشته b
مربوط می شود c
، مربوط به شی a
: b
- به عناصر از شاخص 1 تا 2، c
- به عناصر از شاخص 2 تا 6 (شماره گذاری از 0 شروع می شود، یادآوری). آن ها بدیهی است که هر گونه دسترسی بیشتر به متغیرها b
یا c در JDK 6 در واقع منجر به "شمارش" عناصر مورد نظر آرایه اصلی در پشته می شود. در JDK 7، هر گونه دسترسی بیشتر به متغیرها b
یا c باعث دسترسی به آرایههای کوچکتر ضروری میشود که قبلاً ایجاد شدهاند و در پشتهها "زندگی میکنند". آن ها واضح است که JDK 7 از حافظه فیزیکی بیشتری در موقعیتهایی مانند این استفاده میکند. اما بیایید یک گزینه ممکن را تصور کنیم: رشته های فرعی خاصی از متغیر به متغیرها اختصاص داده می شود b
و در آینده همه فقط از آنها استفاده می کنند - اشیاء و . دیگر هیچ کس به سادگی به متغیر a دسترسی ندارد، هیچ ارجاعی به آن وجود ندارد (این همان چیزی است که نویسنده مقاله منظور می کند). در نتیجه، در یک نقطه از زمان زباله جمعکننده فعال میشود، و (البته در کلیترین شکل) ما 2 وضعیت مختلف دریافت میکنیم: JDK 6 : شی نابود میشود (زباله جمعآوری میشود) ، اما - آرایه عظیم اصلی در پشته زنده است; مدام استفاده می شود و . JDK 7: شی a به همراه آرایه اصلی در پشته از بین می رود. این نکته ای است که در JDK 6 می تواند منجر به نشت حافظه شود. c
a
b
c
a
b
c
5. substring() در JDK 7
این روش در JDK 7 بهبود یافته است. در JDK 7substring()
در واقع یک آرایه جدید روی پشته ایجاد می کند.
//JDK 7
public String(char value[], int offset, int count) {
//check boundary
this.value = Arrays.copyOfRange(value, offset, offset + count);
}
public String substring(int beginIndex, int endIndex) {
//check boundary
int subLen = endIndex - beginIndex;
return new String(value, beginIndex, subLen);
}
GO TO FULL VERSION