+2 امتیاز
قبل در برنامه نویسی توسط (778 امتیاز)
برچسب گذاری دوباره قبل توسط
جاوا call by reference است یا call by value؟

3 پاسخ

+3 امتیاز
قبل توسط (1.2هزار امتیاز)

جاوا از نظر فنی کاملا call by value می باشد هر چند به اشتباه بعضی می گویند که در مورد نوع های غیر primitive به صورت call by reference عمل می کند.

در مورد نوع های primitive که مشخص است جاوا به صورت call by value عمل می کند اما در مورد غیر primitive ها ، چون Object های جاوا در واقعا رفرنس به خانه های حافظه هستند ، زمانی که شما یک Object را برای یک متد می فرستید مقدار آن (که آدرس حافظه است و نه محتوایی که به آن اشاره میکند!) درون پارامتر تابع کپی می شود. برای اثبات این موضوع کد زیر را در نظر بگیرید :


public class JavaCallType {

  public static void main(String[] args){
    Long aNonPrimitive = new Long(123);
    Long afterPassToMethod = changeValue(aNonPrimitive);
    if(aNonPrimitive.equals(afterPassToMethod)){
      System.out.println(aNonPrimitive + "==" + afterPassToMethod);
    }else{
      System.out.println(aNonPrimitive + "!=" + afterPassToMethod);
    }
  }
  
  public static Long changeValue(Long param){
    param = new Long(1234);
    return param;
  }

}

خروجی عبارت 123!=1234 خواهد بود ، اگر جاوا call by refrence بود در این مثال هر دو متغیر عینا یکی می شدند.

قبل توسط (1.2هزار امتیاز)
دقیقا همون اشتباهی که گفتم رو شما کردید ، این چیزی که شما گفتید به این خاطر هست که جفت رفرنس ها در اون حالت برای یک قسمت از حافظه هستند بنابراین تغییر محتوا در یک رفرنس موجب این میشه که شما توسط اون یکی رفرنس تغییرات رو دریافت کنید اما بازم میگم اون چیزی که هنگام فراخوانی متد پاس داده میشه آدرس رفرنس هست ، در حقیقت از رفرنس کپی میشه.
البته به همین توضیحی که شما دادید اینجور به نظر میاد که انگار call by refrence  هست در حالی که اینطور نیست.
قبل توسط (1.2هزار امتیاز)
ساده تر بگم جاوا در مورد نوع های non-primitive هم به صورت کپی کردن عمل می کند، اما چیزی که کپی می شود آدرس آبجکت در حافظه است و نه محتوا.
+2 امتیاز
قبل توسط (20 امتیاز)

اینکه جاوا Pass by Value هست درسته ولی کد تنها چیزی رو ثابت نمی کنه  و این الگوریتم و قواعد JVM هست که کلا مانع گرفتن Reference / Offset میشه  . چرا ؟ به خاطر Garbage Collection / GC.

به خاطر اینکه چون رفرنس ها توسط GC جا به جا می شوند و GC از چندین نوع هستند  میشه ازGC ها Reference Counting / Mark-sweep-compact اسم ببرم که کار درست نداشتن کاربر در رفرنس گردن Mark-sweep-compact GC هست برای اینکه سه مرحله چک می کنه برای مدیریت حافظه :

Mark: چک کردن رفرنس ها و اشیای که مورد استفاده هستند یا در آینده مورد استفاده قرار می گیرند.
sweep : خارج کردن اشیای یا حافظه اشغال شده ای که رفرنسی نداره.
compact : مرتب سازی صورت می گیره که در اینجا رفرنسا جا به جا می شند

Reference Counting تعداد رفرنس های هر شی کلاس متد .... اگر صفر شد از حافظه پاک میشه با چک کردن sweep .


به این نتیجه می رسیم Pass by Reference وجود ندارد چون مخالف طبیعت رفتار GC و JVM هست.
وقتی instance , method  رو به پارامتر می دید کاری به primitive ها نداریم اگر رفرنسی داده بشه اون رفرنس کپی رفرنس اصلی هست :

int[] array = { 1, 2, 3, 4, 5 };

modifyArray(array); // pass array reference

public static void modifyArray(int[] array2)
{
for (int counter = 0; counter < array2.length; counter++)
array2[counter] *= 2;
}

for (int value : array)
System.out.printf("
%d", value);

//2 4 6 8 10
//2 4 6 8 10

جواب یکی ولی الان ۲ رفرنس به یک value دسترسی داره واسه اینکه رفرنس مورد نیازه خود jvm هیچ وقت این اختار رو به شما نمیده چون مدیریت حافظش باهمین رفرنسه که یکی از بزرگترین مزیت های جاواس . GC ها چند نوع هستن فکر کنم ۶ تا باشند که هر کدوم هم به چندین قسمت تقسیم می شوند برای تسلط به آشنای با اینا نیاز داری. در مورد Heap , generational GC , Edan  - young generation , perm - permanent generation , old generation مطالعه داشته باشی خوبه .

+1 امتیاز
قبل توسط (20 امتیاز)

به نظرم کامل ترین مطلب فارسی که در این زمینه هست . از سایت جاواکاپ

سوالات مشابه

+1 امتیاز
1 پاسخ 505 بازدید
+1 امتیاز
1 پاسخ 778 بازدید
0 امتیاز
0 پاسخ 596 بازدید
+1 امتیاز
1 پاسخ 995 بازدید
+1 امتیاز
1 پاسخ 411 بازدید
+2 امتیاز
1 پاسخ 963 بازدید
+1 امتیاز
1 پاسخ 613 بازدید
سوال شده 5 سال قبل در برنامه نویسی توسط Reza.R (851 امتیاز)
...