JavaRush /בלוג Java /Random-HE /תרגום: יצירת אובייקטי מחרוזת ב-Java - באמצעות " " או בנאי...
FellowSparrow
רָמָה
Lvov

תרגום: יצירת אובייקטי מחרוזת ב-Java - באמצעות " " או בנאי?

פורסם בקבוצה
מקור: ליצור מחרוזת Java באמצעות " " או קונסטרוקטור? על ידי X Wang תרגום: יצירת אובייקטי מחרוזת ב-Java - שימושב-Java, ניתן ליצור מחרוזת בשתי שיטות:
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מתייחסים לאותו אובייקט - מחרוזת המוצהרת כמילולית (מחרוזת מילולית למטה) באזור השיטה (אנו מפנים את הקורא למקור במשאב שלנו: Top 8 דיאגרמות להבנת Java , דיאגרמה 8). כאשר אותה מחרוזת מילולית נוצרת יותר מפעם אחת, רק עותק אחד של המחרוזת מאוחסן בזיכרון, רק מופע אחד שלו (במקרה שלנו "abcd"). זה נקרא "התמחות במיתרים". כל קבועי המחרוזות המעובדים בזמן הקומפילציה מאומנים אוטומטית ב-Java. דוגמה 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שקר מכיוון cשהם dמתייחסים לשני אובייקטים שונים בזיכרון (על הערימה). לאובייקטים שונים יש תמיד הפניות שונות. תרשים זה ממחיש את שני המצבים שתוארו לעיל: תרגום: יצירת אובייקטי מחרוזת ב-Java - שימוש

2. מיתרים מתמחים בשלב ביצוע התוכנית

המחבר מודה ללוקאס אדר (ההערה למטה היא שלו): התמחות מחרוזת יכולה להתרחש גם במהלך הפעלת תוכנית, גם אם נוצרות שתי מחרוזות באמצעות בנאים:
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. מה קורה כאשר תת-מחרוזת () נקראת?

אתה אולי יודע שבגלל אי-השינוי x, כאשר מקצה x את התוצאה של x.substring(1,3), xהוא מצביע על שורה חדשה לגמרי (ראה תרשים): תרגום: יצירת אובייקטי מחרוזת ב-Java - שימושעם זאת, דיאגרמה זו אינה נכונה לחלוטין; זה לא מדגים מה באמת קורה בערימה. מה שקורה בפועל כשנקרא substring()שונה ב-JDK 6 וב-JDK 7.

3. substring() ב-JDK 6

סוג המחרוזת נתמך על ידי סוג מערך char. ב-JDK 6, המחלקה Stringמכילה 3 שדות: char value[], int offset, int count. הם משמשים לאחסון מערך התווים בפועל, האינדקס של התו הראשון במערך, מספר התווים בשורה. כאשר השיטה נקראת substring(), היא יוצרת שורה חדשה, אך הערך של המשתנה עדיין מצביע על אותו מערך בערימה. ההבדל בין שתי מחרוזות הוא מספר התווים שלהן וערך האינדקס של התו ההתחלתי במערך. תרגום: יצירת אובייקטי מחרוזת ב-Java - שימושהקוד שלהלן הוא פשוט ומכיל רק את היסודות כדי להדגים את הבעיה.
//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יפנו לשני מערכים שזה עתה נוצרו בערימה- Lfor b, ongLfor c. שני המערכים החדשים הללו יאוחסנו בערימה יחד עם המערך המקורי aLongLongStringשאליו מתייחס א. הָהֵן. המערך המקורי לא נעלם לשום מקום. כעת נחזור ל-JDK 6. ב-JDK 6, ערימה מכילה מערך בודד aLongLongString. לאחר ביצוע שורות הקוד
String b = a.substring(1, 2);
String c = a.substring(2, 6);
אובייקטים bמתייחסים cלאותו מערך בערימה, המתאים לאובייקט a: b- לאלמנטים מהאינדקס הראשון עד ה-2, c- לאלמנטים מהאינדקס השני עד ה-6 (המספור מתחיל מ-0, תזכורת). הָהֵן. ברור שכל גישה נוספת למשתנים bאו c ב-JDK 6 תגרום למעשה לכך שהאלמנטים הרצויים של המערך המקורי "ייספרו" בערימה. ב-JDK 7, כל גישה נוספת למשתנים bאו c תגרום לגישה למערכים הקטנים יותר הדרושים, שכבר נוצרו ו"חיים" בערימה. הָהֵן. ברור ש-JDK 7 משתמש יותר פיזית בזיכרון במצבים כאלה. אבל בואו נדמיין אפשרות אפשרית: מחרוזות משנה מסוימות של המשתנה מוקצות למשתנים b, ובעתיד כולם משתמשים רק בהם - אובייקטים ו . אף אחד פשוט לא ניגש יותר למשתנה a; אין לו התייחסות (לכך מתכוון מחבר המאמר). כתוצאה מכך, בשלב מסוים בזמן, אוסף האשפה מופעל, ו(בצורה הכללית ביותר, כמובן) אנו מקבלים 2 מצבים שונים: JDK 6 : החפץ נהרס (אשפה נאסף) , אבל - הענק המקורי המערך בערימה חי; הוא נמצא בשימוש כל הזמן ו . JDK 7: אובייקט a מושמד יחד עם המערך המקורי בערימה. זו הנקודה ב-JDK 6 שיכולה להוביל לדליפת זיכרון. cabcabc

5. substring() ב-JDK 7

השיטה שופרה ב-JDK 7. ב-JDK 7 substring()הוא למעשה יוצר מערך חדש בערימה. תרגום: יצירת אובייקטי מחרוזת ב-Java - שימוש
//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);
}
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION