השוואת מחרוזות ב JAVA

חכם?

לדעתי זה בכלל לא חכם ואפילו די תמוהה. הסיבה שהבחורה ששאלה את השאלה היא בדיוק הסיבה שבגללה אסור לקומפיילר לעשות כזאת הנחה משונה.
 
בטח שמותר לו..

למה שיהיה אסור לו לעשות את זה? הקומפיילר יכול לייצר קוד "חכם" שייצור אובייקט יחיד וששני המצביעים יצביעו אליו. אבל כשתתבצע כתיבה לאובייקט באמצעות אחד המצביעים יווצר עותק חדש של האובייקט הזה, המצביע יצביע אליו, וכל השינויים יבוצעו עליו. קוראים לטריק הזה copy on write, והוא חוקי למהדרין.
 

neko

New member
מאד מאד חכם.

קומפיילר טוב הוא קומפיילר שיודע לחסוך זמן וזכרון שהמתכנתים עליו מבזבזים בלי לשים לב. ההנחה הזאת ממש לא משונה - הקומפיילר רואה שתי מחרוזות זהות. למה לעזאזל שהוא יבנה להם שתי הקצאות בזכרון??? ובכלל, מה אתה עושה כאן, מחוץ לפורום שינוי? לא ראיתי אותך מאז הבחירות
 
בגלל -../images/Emo26.gif

שאם המשתמש דאג לייצר שני אובייקטים שונים - אז כנראה הוא התכוון לשני אובייקטים שונים! ובהיבט של Java, כשאתה משתמש באופרטור == אתה למעשה שואל אם s1 ו-s2 מצביעים לאותו אובייקט. והתשובה היא חד משמעית לא! זו בדיוק הסיבה ל"למה לעזאזל לבנות להם שתי הקצאות בזיכרון". אם הייתי רוצה שהקומפיילר יחסוך מקום - הייתי כותב:
String s1 = "ABC"; String s2 = s1;​
ואם החלטתי לא לכתוב את זה ככה - אז יש לי (כנראה) סיבה טובה לכך.
 

desertboy

New member
אתה טועה

אם משתמש היה רוצה ליצר שני אוביקטים שונים היה משתמש ב new, שמוש ב = ב string ב java גורם לתרגום הביטוי ע"י הקומפיילר למשהו בסגנון של : |פקוד| new StringBuffer().append("..."); ומכיון ש StringBuffer הוא implicit shared מתקבלת התוצאה הנ"ל בכל אופן לא תראה שבשום מסמך של sun מוגדרת ההתנהגות שהמחבר כתב , הבעיה התחילה בכך שהוא עשה מספר ניסיונות והגיעה למסקנה מתוך זה.
 

selalerer

New member
ציטוט מתוך Thinking in Java:

.... and each object can be uniquely distinguished from every other object—to put this in a concrete sense, each object has a unique address in memory​
הוא מדבר פה על תכונות של OOP בכללי עוד לפני שהוא נכנס לJava.
 

neko

New member
STRING-ים זהים הם אותו אובייקט.

גם SCHEME עובדת ככה - מחרוזות זהות אינן תופסות זכרון נוסף. זה נוח בעיקר בגלל שSTRING הוא IMMUTABLE.
 

voguemaster

New member
זה תלוי אורי

באובייקטים באופן כללי אתה צודק, האופרטור == בודק אם הם אותו אובייקט ע"י בדיקה של הרפרנס. אבל, עבור אובייקטים שמומשה בהם equals בצורה אחרת, כמו String, מבוצעת השוואת מחרוזות. זה יותר נכון לעשות את זה כך וזה משפיע על ההתנהגות של כמה וכמה דברים אחרים. אני אתן דוגמא. נניח שבנית combobox מסוים. הוא כמובן מורכב מכמה אופציות כולן כמובן מחרוזות. אם תרצה לבצע set לאחת מהאופציות ע"י קריאה לפונק' והעברת השם של האופציה שאתה רוצה לבחור, תגלה שמבוצעת השוואה של המחרוזות. זה אולי יפתיע אותך לגלות שבתיעוד של סאן כתוב שמבוצעת השוואה ע"י eqauls ובמחרוזות זה מיתרגם בדיוק להשוואה של מחרוזות. עליתי על הנושא הזה כי העברתי מחרוזת שבה אחת האותיות בעלת CASE שונה מזו של האופציה התואמת ב-combobox. לכן הייתי צריך לבצע השוואה בעצמי ע"י equalsIgnoreCase.
 
חוץ מלימוד של הגדרות השפה...

אני לא כל-כך רואה איך זה משנה... אם אתה רוצה להשוות בין מחרוזות - אתה בכל מקרה תשתמש ב-equals... ככה שכל הדיון הזה הוא לא באמת עקרוני... מה באמת מוגדר ב-spec של Java לגבי הדוגמה שהיא הביאה מהספר?... (או שההתנהגות של הקומפיילר לא מוגדרת במקרה הזה?..)
 

voguemaster

New member
ממה שידוע לי..

שני ה-IFים שיש שם עושים בדיוק את אותו הדבר, משתמשים ב-equals, שעבור מחרוזת מבצע השוואה (עם CASE).
 
כלומר - מחרוזת היא יוצאת-דופן?...

לכל אובייקט אחר - השימוש באופרטור == והשימוש ב-equals הם שני דברים שונים לגמרי...
אופרטור == בודק האם מדובר ב-reference-ים לאותו אובייקט
המתודה equals מוגדרת ע"י המשתמש (איפשהו בעץ הירושה) קל לראות שהמתודה equals מאוד פתוחה לשינוי... במחלקה Object למשל היא פועלת בדיוק כמו אופרטור ==... ואם אני כותב מחלקה משלי - אני יכול להחליט שרירותית מה היא תחזיר (למשל - true אם היום יום רביעי, ו-false אחרת...
) לעומת זאת, לאופרטור == אין את הגמישות הזו... הוא תמיד מבצע את אותה פעולה (בודק האם מדובר ב-reference-ים זהים). ככה שאם עבור מחרוזות זה מוגדר אחרת - זה הופך את ההתנהגות של האופרטור הזה לחריגה - רק עבור String...
(או כמו שהזכירו - ההתנהגות לא חריגה, אבל הקומפיילר יוצר instance אחד עבור שתי ההצהרות והאתחולים של ה-String-ים בדוגמה מהספר...)
 

voguemaster

New member
לפי דעתי זה הפוך

לפי דעתי אופרטור == מתורגם לקריאה ל-equals ועבור מרבית האובייקטים מבוצעת השוואת רפרנסים כדי לראות אם מדובר באותו אובייקט. לעומת זאת ב-String הם מימשו את equals מחדש כדי לבצע השוואה. לא זכור לי איפה ראיתי את זה אבל that's my take on the sbject. מעניין מה הם עשו שם באמת
 
זהו - שלא נראה לי...

אופרטור == לא "מכיר" את המתודה equals... יש מקרים בהם equals מכירה את אופטור == (ומשתמשת בו) - תלוי במימוש מן-הסתם. תראה כאן את התיעוד של equals של Object - כתוב שם במפורש שהמימוש שם הוא המימוש הכי "discriminating" של equals - שימוש באופרטור ==...
 

desertboy

New member
האופרטור ==

לא מתורגם בג'אווה (זה יותר מושג של c++) הוא משווה רפרנסים , השויון שהתקבל בדוגמה הנ"ל הוא בגלל שהם באמת אותו אובייקט . כמו שציינתי כבר שמוש ב new ליצירה היה גורם ליצירת רובייקט חדש דבר שמוגדר שמוש ב "" להשמה גורם לקריאה ל StringBuffer שהשמוש שלו בזיכרון מבוצע בצורה חכמה יותר.
 
למעלה