קטע קוד בג'אוה - פלט

קטע קוד בג'אוה - פלט

להלן קטע קוד בג'אוה:
קוד:
public class Number  {
  private int i;

  public Number() {
     i=15;
  }

  public int getI() {
     return i;
  }
     
  public void setI(int x) {
     i = x;
  }
}

public static void foo1()  {
   int i = 5;
   Number  n = new Number();
   n.setI(10);
   foo2(n, i);
                                   
   System.out.println(n.getI());
}
        
public static void foo2(Number n2, int i){
   n2.setI(30);
   i = 10;
   Number num = new Number();
   n2 = num;
   System.out.println(n2.getI());
}

public static void main(String[] args){
   foo1();
}
אשמח בבקשה אם מישהו יסביר לי מדוע הפלט המתקבל הוא
קוד:
15
30
ולא
קוד:
15
15
?

איך הגיעו ל-30 בשורה השניה של הפלט?
 

BravoMan

Active member
כי reference

כדי להבין איך הקוד עובד, צריך להבין איך מעבירים פרמטרים לפונקציה ב-Java.
כל פרמטר שאינו פרימיטיבי, כלומר כל פרמטר מטיפוס מחלקה, מעבירים by reference.
&nbsp
לכן, השורה n2 = num מחליפה reference שמחזיק משתנה n2, ולא נוגעת בתוכן האובייקט המקורי.
 

BravoMan

Active member
וזה בדיוק מה שקורה כשאתה מפעיל את המתודה setI.

אבל השורה עם ה-= (אופרטור השמה) לא פועלת על האובייקט, אלא על משתנה שמחזיק את הרפרנס עצמו, ומחליפה את הרפרנס שהמשתנה מחזיק.
&nbsp
אם אתה מכיר מצביעים, אז תחשוב על המצב בו אתה דורס מצביע עם מצביע אחר - אתה לא משנה את תוכן הזיכרון אליה מצביע המצביע.
 
אבל בתכנית, הפונקציה foo2 מדפיסים את ערך i של המשתנה n

(ערך ששווה 15, כי המשתנה n מצביע על המשתנה n2), ואז הפונקציה הנ"ל מסיימת תפקידה והתכנית מדפיסה שוב (בשורה האחרונה של ה-main) את ערך i של המשתנה n (שהוא עדיין שווה 15, כי n הרי מצביע ל-n2), אז למה 30 בסוף?
 

BravoMan

Active member
לא.

הפונקציה foo1 לא יודעת שפונקציה foo2 יצרה אובייקט חדש שהיא שמרה במשתנה מקומי num.
&nbsp
foo1 שולחת reference - קרא לזה "קישור" לאובייקט Number שהיא יצרה ושמרה במשתנה מקומי n לפונקציה foo2.
&nbsp
foo2 שמה בתוך האובייקט הזה ערך 30 בשורה הראשונה n2.setI(30);
&nbsp
אחרי זה, היא זורקת את הקישור הזה לפח, כך שהיא לא יכולה לשנות יותר את האובייקט ש-foo1 שלחה לה.
&nbsp
foo2 יוצרת אובייקט חדש, שמה קישור אליו ב-n2 שהוא למעשה משתנה מקומי שלה, ובכך מנתקת כל קשר עם n שהיא קיבלה, ואז מדפיסה את האובייקט החדש.
&nbsp
עכשיו ברור?
&nbsp
&nbsp
 
הבנתי, זה משתנה שמת עם מותה של הפונקציה. ובאיזה אופן היה

צריך לשנות את הקוד כדי שגם הפלט של השורה השניה יהיה 15 (ולא 30) ? להוסיף & לפני המשתנה ששולחים לפונקציה ?
 

BravoMan

Active member
ב-Java האופרטור & משמש רק לחישוב AND על סיביות

לא קיים אופרטור "כתובת" כמו שיש ב-C ו-++C.
&nbsp
הקוד בתרגיל הוא קוד לדוגמה וחסר משמעות, כך שיש 1001 דרכים לשנות אותו כדי לקבל תוצאה שאתה רוצה.
&nbsp
למשל, foo2 יכולה להחזיר את האובייקט החדש שהיא יצרה ו-foo1 תדפיס את הערך של האובייקט החוזר, במקום n שלה.
&nbsp
או, foo2 יכולה לשמור בצד את ה-reference ל-n ולהחזיר אותו ל-15 לפני שהיא מסתיימת.
או אפשר פשוט למחוק את השורה שקובעת ערך לש n ל-30.
&nbsp
תבחר מה שהכי מתאים לך.
 
למעלה