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