ריק או לא ריק?

הפוסט הזה עוסק בריקנות. שזה נשמע אולי מוזר, אבל המושג “ריק” בשפת תכנות הוא מושג בעייתי, בייחוד כשמתעסקים בתאי זיכרון. תא זיכרון לא יכול להיות ריק, זה לא הגיוני. כיוון שתאי הזיכרון במחשב הם ישויות פיסיות, יש בהם אפסים או אחדים (בצורת שדות מגנטיים). לא יכול להיות שבתא זיכרון לא יהיה כלום, המושג לא קיים.

מצד שני, אנחנו בתור מתכנתים בהחלט משתמשים במושג “ריק” בנוגע למשתנים ותאי זיכרון. כשאנחנו אומרים את זה, הכוונה היא שתא הזיכרון לא מכיל ערך שאנחנו הצבנו בעצמנו. ההתייחסות שלנו לריקנות המדומה הזאת תלויה בהקשר של התוכנית שאנחנו כותבים.

אבל המצב נהיה מסובך יותר כשמדובר באובייקטים. כיוון שאובייקטים מכילים בעצם שני דברים – המשתנה שמצביע על האובייקט, ומכיל את הכתובת שלו, והאובייקט עצמו, שנמצא בערימה ומכיל את הנתונים עצמם. השאלה היא מה הכוונה לאובייקט ריק? ג’אווה מייחדת את המילה השמורה null כדי לציין שמצביע לא מצביע כרגע על אף אובייקט, וזה אומר שהאובייקט ריק.

והמצב נהיה אפילו יותר מוזר כשמדובר במחרוזות, אולי האובייקטים הכי שימושיים באינטראקציה בין בני אדם למחשב. המחלקה String מייצגת בג’אווה מחרוזת, וניתן ליצור ממנה אובייקטים כדי להגדיר מחרוזות.

הרבה פעמים נרצה לדעת האם משתנה מסויים מסוג String מייצג מחרוזת ריקה. למשל, אם המשתמש היה אמור להזין נתון אבל לא הזין כלום. או ששיטה אמורה להחזיר הודעה, והחזירה מחרוזת ריקה. בדיקה של ריקנות המחרוזת היא בדיקה חשובה. הנה הצעה לשיטה שמקבלת מחרוזת, ומחזירה true אם המחרוזת ריקה, ו-false אם לא:

public boolean isEmpty(String s) {

                return s.equals(“”);

}

לכאורה, מאוד פשוט והגיוני – מחרוזת ריקה היא מחרוזת שלא מכילה אף תו, ולכן ניתן להשוות את הפרמטר s ל-“” באמצעות השיטה equals של String ולקבל תשובה. העניין הוא שהפרמטר s הוא אובייקט, ולכן המושג של “ריק” יכול להיות גם אם האובייקט עצמו שווה ל-null. למשל, אם נקרא לשיטה כך:

String s = null;

System.out.println(isEmpty(s));

נקבל שגיאת ריצה, כיוון שאין אפשרות להפעיל שיטה על אובייקט שהוא null.

אנחנו יכולים כמובן לשאול האם s == null ובכך לדעת אם המחרוזת ריקה, אבל זה רק היבט אחד של הריקנות – המחרוזת היא ריקה או כי האובייקט שמייצג אותה שווה ל-null או כי האובייקט קיים, אבל מכיל נתון ששווה ערך למחרוזת ריקה, כלומר ל-“”.

מימוש טוב יותר של השיטה –

public boolean isEmpty(String s) {

return s == null || s.equals(“”);

}

כעת השיטה isEmpty מכסה את שני מקרי הריקנות של המחרוזת.

נ.ב.

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

נ.ב. #2

האם לדעתכם אפשר היה לכתוב את משפט ה-return  בשיטה כך:

return s.equals(“”) || s == null;