מה זו מחרוזת (String)
String מחזיק רצף של תווים: טקסט כמו שם, משפט או שורה שנקראה מקובץ. ראיתם את String ברשימת טיפוסי ההפניה בעמוד הקודם, וכאן תעבדו איתו בפועל. כותבים ליטרל מחרוזת בתוך מרכאות כפולות (מרכאות בודדות שמורות ל-char יחיד):
name.length() מחזירה את מספר התווים: 3 עבור "Ada". זו קריאה למתודה, ולכן היא צריכה סוגריים.
חיבור מחרוזות
האופרטור + מדביק מחרוזות זו לזו. אם אחד הצדדים של + הוא מחרוזת, הצד השני מומר לטקסט אוטומטית, כך שאפשר לשלב מספרים וערכים בוליאניים בלי עבודה נוספת:
מלכודת אחת: מכיוון ש-+ מחושב משמאל לימין, "" + 1 + 2 נותן "12" (מחרוזת ועוד int, ואז שוב מחרוזת ועוד int), אבל 1 + 2 + "" נותן "3" (שני המספרים השלמים מתחברים קודם, ורק אז הופכים לטקסט). כשיש ספק, עטפו את החישוב בסוגריים.
מחרוזות הן immutable
זה הדבר החשוב ביותר להבין על מחרוזות ב-Java: String אף פעם לא משתנה אחרי שנוצר. כל מתודה ש"משנה" מחרוזת בעצם מחזירה מחרוזת חדשה לגמרי ומשאירה את המקורית כמו שהיא. לכן אם שוכחים לשמור את ערך ההחזרה, שום דבר לא קורה:
הקריאה הראשונה מחשבת את "HELLO" וזורקת אותו מיד. רק השורה השנייה, שמשימה בחזרה ל-s, משפיעה בצורה נראית לעין. כמעט כולם נופלים בזה לפחות פעם אחת.
השוואת מחרוזות
השתמשו ב-.equals() כדי להשוות את התוכן של שתי מחרוזות. שימוש ב-== הוא טעות המתחילים הקלאסית: == שואל "האם אלה אותו אובייקט בזיכרון?", ולא "האם הם מכילים את אותו טקסט?":
כאן a == b הוא false כי new String(...) מכריח יצירה של אובייקט נפרד. השוו תמיד ערכי מחרוזות עם .equals() (או עם .equalsIgnoreCase() כדי להתעלם מאותיות גדולות וקטנות). טריק שימושי כדי להימנע מקריסה כשאחד הצדדים עלול להיות null הוא לקרוא ל-.equals על הליטרל: "yes".equals(input) אף פעם לא זורקת חריגה, גם אם input הוא null.
מתודות String יומיומיות
מכיוון שמחרוזות הן immutable, כל אחת מהמתודות האלה מחזירה מחרוזת חדשה (או ערך) במקום לשנות את המקורית. אלה המתודות שתשתמשו בהן כל הזמן:
שימו לב לשרשור הקריאות: s.trim().toUpperCase() עובד כי trim() מחזירה מחרוזת, ועליה קוראים אחר כך ל-toUpperCase(). גם substring היא מתודה שימושית מאוד: היא מקבלת אינדקס התחלה (כולל) ואינדקס סיום אופציונלי (לא כולל):
האינדקסים מתחילים מאפס, כך ש-substring(0, 4) לוקחת את התווים 0 עד 3. בקשה של אינדקס שנמצא אחרי הסוף זורקת StringIndexOutOfBoundsException, אחת מהחריגות בזמן ריצה שאפשר להתגונן מפניהן. שימו לב גם ש-split(",") שלמעלה מחזירה מערך, ושם length הוא שדה בלי סוגריים, בניגוד למתודה .length() של מחרוזת.
בניית מחרוזות בתוך לולאה
שרשור עם + מתאים לכמה חלקים, אבל בתוך לולאה גדולה הוא איטי: כל + יוצר מחרוזת חדשה ומעתיק את הכל. כשמרכיבים טקסט בלולאה, השתמשו ב-StringBuilder, שמשנה חוצץ במקום ומפיק את המחרוזת הסופית פעם אחת בסוף:
append מחזירה את אותו builder, ולכן אפשר לשרשר את הקריאות. קראו ל-.toString() כדי לקבל String רגיל בסוף. לחיבורים חד פעמיים הישארו עם +; לצבירה של הרבה חלקים, StringBuilder הוא הכלי הנכון.
הבא בתור: עיצוב מחרוזות
שרשור הופך למבולגן ברגע שצריך עמודות מיושרות, מספר קבוע של ספרות אחרי הנקודה או מספרים מרופדים. String.format ו-printf של Java משתמשות בתבנית עם מצייני % כדי לטפל בכל זה בצורה נקייה, וזה הנושא של העמוד הבא.
שאלות נפוצות
איך משווים שתי מחרוזות ב-Java?
משתמשים ב-.equals() כדי להשוות תוכן: a.equals(b) מחזירה true כשהתווים זהים. אל תשתמשו ב-== כדי להשוות ערכי מחרוזות: == משווה הפניות לאובייקטים, ולכן היא עלולה להחזיר false עבור שתי מחרוזות שמכילות את אותו טקסט. השתמשו ב-.equalsIgnoreCase() כשאותיות גדולות וקטנות לא אמורות לשנות.
למה מחרוזות ב-Java הן immutable?
אחרי שאובייקט String נוצר, אי אפשר לשנות אותו לעולם. מתודות כמו replace או toUpperCase מחזירות מחרוזת חדשה במקום לשנות את המקורית. אי השינוי הופך מחרוזות לבטוחות לשיתוף ולשמירה במטמון, אבל המשמעות היא שצריך להשים את התוצאה: s = s.toUpperCase();. אם קוראים למתודה ומתעלמים מערך ההחזרה שלה, שום דבר לא קורה.
איך מקבלים את האורך של מחרוזת ב-Java?
קוראים למתודה .length(): "hello".length() מחזירה 5. שימו לב שב-String זו מתודה עם סוגריים, בניגוד למערכים, שבהם length הוא שדה בלי סוגריים (arr.length).