הקדמה
רבים ממתכנתי Java שואלים אם Java היא מעבר לערך או מעבר לכתובת. מאמר זה מסכם למה Java היא תמיד מעבר לערך.
ראשית, מהו מעבר לערך ומעבר לכתובת?
- מעבר לערך: ערכי הפרמטרים של השיטה מועתקים למשתנה אחר ואז העתק האובייקט מועבר לשיטה. השיטה משתמשת בהעתק.
- מעבר לכתובת: פיענוח או כתובת לפרמטר המקורי מועבר לשיטה. השיטה גוששת לפרמטר המקורי.
לעיתים קרובות, הבלבול סביב המונחים הללו הוא תוצאה של המושג של הקישור לאובייקט ב-Java. מבחינה טכנית, Java היא תמיד מעבר לערך, מכיוון שאף על פי שמשתנה עשוי להחזיק קישור לאובייקט, קישור האובייקט הוא ערך שמייצג את מיקומו של האובייקט בזיכרון. קישורים לאובייקט מועברים לכן לפי ערך.
כל סוגי הנתונים המציינים כתובת וסוגי הנתונים הפרימיטיביים מועברים לפי ערך. למדו עוד על סוגי הנתונים ב-Java.
בנוסף להבנה של סוגי הנתונים, חשוב גם להבין הקצאת זיכרון ב-Java, מכיוון שסוגי הנתונים המציינים כתובת וסוגי הנתונים הפרימיטיביים מאוחסנים בדרכים שונות.
הדגמה של העברת ערך לפי ערך
הדוגמה הבאה מדגימה כיצד ערכים מועברים ב-Java.
התוכנית הדוגמאית משתמשת במחלקה הבאה:
public class Balloon {
private String color;
public Balloon() {}
public Balloon(String c) {
this.color = c;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
התוכנית הדוגמאית הבאה משתמשת בשיטה גנרית, swap()
, שמחליפה שני משתנים. שיטה נוספת, changeValue()
, מנסה לשנות את ערכי המשתנים.
public class Test {
public static void main(String[] args) {
Balloon red = new Balloon("Red"); // מצביע לזיכרון = 50
Balloon blue = new Balloon("Blue"); // מצביע לזיכרון = 100
swap(red, blue);
System.out.println("After the swap method executes:");
System.out.println("`red` color value = " + red.getColor());
System.out.println("`blue` color value = " + blue.getColor());
changeValue(blue);
System.out.println("After the changeValue method executes:");
System.out.println("`blue` color value = " + blue.getColor());
}
// שיטת החלפה גנרית
public static void swap(Object o1, Object o2){
Object temp = o1;
o1 = o2;
o2 = temp;
}
private static void changeValue(Balloon balloon) { // בלון = 100
balloon.setColor("Red"); // בלון = 100
balloon = new Balloon("Green"); // בלון = 200
balloon.setColor("Blue"); // בלון = 200
}
}
כאשר אתה מפעיל את תוכנית הדוגמה, אתה מקבל את הפלט הבא:
OutputAfter the swap method executes:
'red' color value = Red
'blue' color value = Blue
After the changeValue method executes:
'blue' color value = Red
הפלט מראה כי שיטת swap()
לא החליפה את ערכי הצבע של האובייקטים המקוריים. זה עוזר להראות ש-Java היא עוברת לפי ערך, מאחר ושיטת swap()
פועלת רק על העתקים של ערכי הצבע המקוריים של האובייקטים.
בדיקת שיטת swap()
זו יכולה לשמש עם כל שפת תכנות כדי לבדוק האם היא עוברת לפי ערך או לפי עצם.
שיטת ה־swap() בדוגמה מוסברת
כאשר אתה משתמש באופרטור new
כדי ליצור מופע של מחלקה, האובייקט נוצר והמשתנה מכיל את המיקום בזיכרון שבו נשמר האובייקט.
Balloon red = new Balloon("Red");
Balloon blue = new Balloon("Blue");
הנה פירוט שלב אחר שלב של מה קורה כאשר שיטת ה־swap() מבוצעת:
-
נניח ש־
red
מצביע למיקום זיכרון 50 ו־blue
מצביע למיקום זיכרון 100, ושאלו הם מיקומי הזיכרון של שני אובייקטים מסוגBalloon
. -
כאשר המחלקה קוראת לשיטת ה־swap() עם המשתנים
red
ו־blue
כארגומנטים, שני משתנים חדשים של אובייקט,o1
ו־o2
, נוצרים.o1
ו־o2
גם מצביעים למיקומי זיכרון 50 ו־100 בהתאמה. -
הקטע הקוד הבא מסביר מה קורה בתוך השיטה
swap()
:public static void swap(Object o1, Object o2) { // o1 = 50, o2 = 100 Object temp = o1; // מעביר את ערך ההפניה לאובייקט של o1 לתוך temp: temp = 50, o1 = 50, o2 = 100 o1 = o2; // מעביר את ערך ההפניה לאובייקט של o2 לתוך o1: temp = 50, o1 = 100, o2 = 100 o2 = temp; // מעביר את ערך ההפניה לאובייקט של temp לתוך o2: temp = 50, o1 = 100, o2 = 50 } // השיטה הסתיימה
-
ערכי
o1
ו־o2
הוחלפו, אך מאחר שהערכים הם העתקים של מיקומי זיכרון ה־red
וה־blue
, אין שינוי בערכי צבעי ה־red
וה־blue
.
מכיוון שהמשתנים מכילים את ההפניה לאובייקטים, זו טעות נפוצה להניח שאתה מעביר את ההפניה ושגם ג'אווה היא עוברת על ידי הפניה. אך, אתה מעביר ערך שהוא העתק של ההפניה ולכן זהו עבור על ידי ערך.
הדוגמה changeValue()
נסברת
השיטה הבאה בדוגמה משנה את ערך הצבע של האובייקט שאליו מתייחסת המשתנה blue
:
private static void changeValue(Balloon balloon) { // balloon = 100
balloon.setColor("Red"); // balloon = 100
balloon = new Balloon("Green"); // balloon = 200
balloon.setColor("Blue"); // balloon = 200
}
נכון להכניס לפרטים את השלבים בשיטה changeValue()
:
-
המחלקה קוראת לשיטת
changeValue()
על המשתנהblue
שמתייחס למיקום זיכרון 100. השורה הראשונה יוצרת הפניה שגם מצביעה למיקום זיכרון 100. ערך הצבע של האובייקט במיקום זיכרון 100 משתנה ל-"Red"
. -
השורה השנייה יוצרת אובייקט חדש (עם ערך צבע
"Green"
). האובייקט החדש נמצא במיקום זיכרון 200. כל השיטות הבאות שמתבצעות על המשתנהballoon
פועלות על האובייקט במיקום זיכרון 200, ואין להן השפעה על האובייקט במיקום זיכרון 100. המשתנה החדשballoon
מחליף את ההפניה שנוצרה בשורה 1 וההפניה ל־balloon
מהשורה 1 לא נגישה יותר בתוך השיטה הזו. -
השורה השלישית משנה את ערך הצבע של האובייקט החדש
Balloon
בכתובת הזיכרון 200 ל־"כחול"
, אך לא משפיעה על האובייקט המקורי שנמצא בהפניה שלblue
בכתובת הזיכרון 100. זה מסביר למה השורה הסופית של פלט תכנית הדוגמה מדפיסהערך צבע blue = אדום
, המשקף את השינוי משורה 1.
מסקנה
במאמר זה, למדת על כך למה Java היא שפת תכנות "עוברת לפי ערך". המשך ללמוד עם מדריכי Java נוספים.
Source:
https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference