פרמטרים מאפשרים למתודה לקבל קלט
מתודה שתמיד עושה את אותו הדבר מוגבלת. פרמטרים הם הקלטים שמצהירים עליהם בתוך הסוגריים של המתודה, כדי שאותה מתודה תוכל לעבוד על ערכים שונים בכל פעם שקוראים לה.
רושמים כל פרמטר עם טיפוס ושם. בתוך גוף המתודה, פרמטר מתנהג כמו משתנה מקומי רגיל שכבר מכיל את מה שהקורא העביר.
name הוא הפרמטר. "Sam" ו-"Alex" הם הארגומנטים: הערכים הקונקרטיים שמסופקים בקריאה. הגדרת מתודה אחת, שני פלטים שונים.
פרמטרים מול ארגומנטים
שתי המילים האלה משמשות לפעמים בערבוביה, אבל כדאי לשמור על ההבחנה:
- פרמטר הוא ממלא המקום בהצהרה:
String name. - ארגומנט הוא הערך שמעבירים בפועל:
"Sam".
כלומר void greet(String name) מצהירה על פרמטר, ו-greet("Sam") מעבירה ארגומנט. כשמישהו אומר "המתודה הזו מקבלת שני פרמטרים", הוא מתכוון להצהרה; "העברתי שני ארגומנטים" מתייחס לקריאה.
כמה פרמטרים
מפרידים פרמטרים בפסיקים ונותנים לכל אחד טיפוס משלו. אי אפשר לשתף טיפוס בין שני פרמטרים כמו שאפשר בהצהרת משתנים:
ארגומנטים מותאמים לפרמטרים אך ורק לפי מיקום, לא לפי שם. describe("Sam", 30, true) עובדת כי הסדר מתאים ל-(String name, int age, boolean active). אם מחליפים בין שני ארגומנטים מטיפוסים תואמים, מקבלים באג לוגי שקט, לא שגיאת קומפילציה, ולכן הסדר חשוב.
טעות נפוצה היא לכתוב int add(int a, b). כל פרמטר צריך טיפוס משלו: int add(int a, int b).
החזרת ערך
פרמטרים הם הדרך שבה נתונים נכנסים פנימה; ערך ההחזרה הוא הדרך שבה תוצאה יוצאת החוצה. מצהירים על טיפוס ההחזרה לפני שם המתודה, ומשתמשים ב-return כדי להחזיר ערך לקורא:
טיפוס ההחזרה (double) חייב להתאים למה שמחזירים בפועל עם return. מתודה שהוצהרה כ-void לא מחזירה כלום: היא עדיין יכולה להשתמש ב-return; לבד כדי לצאת מוקדם, אבל לא יכולה להחזיר ערך. ברגע ש-return רץ, המתודה מסתיימת והשליטה חוזרת למקום הקריאה.
Java מעבירה לפי ערך
זה מבלבל כמעט את כולם בהתחלה. כשמעבירים ארגומנט, Java מעתיקה את הערך לתוך הפרמטר. בטיפוסים פרימיטיביים המשמעות היא שהמתודה מקבלת עותק משלה: שינוי הפרמטר אף פעם לא נוגע במשתנה של הקורא:
x נשאר 5. המתודה שינתה את העותק שלה של המספר, לא את המקור.
העברת אובייקטים: עדיין לפי ערך, אבל שימו לב להפניה
אובייקטים נראים כמו חריג, אבל הם לא. מה שמועתק הוא ההפניה (החץ שמצביע על האובייקט), לא האובייקט עצמו. לכן המתודה מצביעה על אותו אובייקט ויכולה לשנות אותו, וזו בדיוק הסיבה שהוספה ל-ArrayList משותף בתוך מתודה נראית גם לקורא:
שתי תוצאות שונות, כלל אחד. addItem הולכת לפי ההפניה ומשנה את הרשימה האמיתית, ולכן הקורא רואה את new מופיע. replace משייכת את הפרמטר לרשימה חדשה לגמרי, אבל זה רק מפנה מחדש את העותק המקומי של ההפניה, כך שה-list של הקורא לא משתנה. המסקנה: אפשר לשנות אובייקט דרך פרמטר, אבל אי אפשר לגרום למשתנה של הקורא להצביע למקום חדש.
הבא: העמסת מתודות
עכשיו אתם יודעים איך להזין למתודה בדיוק את הקלטים שהיא צריכה. אבל מה אם רוצים ששם מתודה אחד יקבל קבוצות שונות של פרמטרים, למשל print(int) ו-print(String)? זו העמסת מתודות (method overloading), וזה העמוד הבא.
שאלות נפוצות
מה ההבדל בין פרמטר לארגומנט ב-Java?
פרמטר הוא המשתנה שמופיע בשמו בהצהרת המתודה: String name ב-void greet(String name). ארגומנט הוא הערך בפועל שמעבירים כשקוראים למתודה: greet("Sam") מעבירה את הארגומנט "Sam". בקיצור: פרמטרים נמצאים בהגדרה, ארגומנטים נמצאים בקריאה.
האם Java מעבירה לפי ערך או לפי הפניה?
Java תמיד מעבירה לפי ערך (pass-by-value). בטיפוסים פרימיטיביים מועבר עותק של הערך, ולכן השמה מחדש לפרמטר לא יכולה לשנות את המשתנה של הקורא. באובייקטים מועבר עותק של ההפניה: אפשר לשנות את האובייקט שההפניה מצביעה עליו (למשל להוסיף לרשימה), אבל השמה מחדש לפרמטר עצמו לא משפיעה על המשתנה של הקורא.
איך מעבירים כמה ארגומנטים למתודה ב-Java?
רושמים את הפרמטרים בהצהרה מופרדים בפסיקים, לכל אחד טיפוס משלו: int add(int a, int b). קוראים לה עם ארגומנטים באותו סדר: add(2, 3). Java מתאימה ארגומנטים לפרמטרים אך ורק לפי המיקום, לא לפי השם, ולכן הסדר חייב להתאים.