مثلا في سي نستعمل Pointer * و في الباسكال نستعمل كلمة var
في الجافا كيف نقوم بـ pass by reference ؟
في الجافا المتغيرات من نوع ال primitive مثل int, float, boolean .. لا يمكن تمريرها by reference وفقط نرسل ال value اي انها pass by value
اما المتغيرات من نوع reference (التي تنشئها من الكلاسات) فهي دائماً ترسل ك pass by reference دون ان تستخدم * او غيرها ..
مثلاً
List l = new ArrayList();
putData(l); // put 4 element in l
System.out.println(l.size()); // print 4
اسمح لي أخي الكريم أن أعقب عليك
لا يوجد في الجافا شيء اسمه pass by reference سواء كان متغيرا أوليا او كائنا ، لا يوجد إلا التمرير بالقيمة ومعنى هذا ان المتغير الذي يمرر إلى الدالة لا يمكن التعديل على قيمته وإنما يجوز استعمالها
مثال لل primative variable
int x=5;
int testMethod(int par){
par =10;
return par;}
فعند التنفيذ فلو استدعينا الدالة testMethod و مررنا إليها المتغير x فسترجع بالقيمة 10 ثم لو استدعينا المتغير x للطباعة فسيظهر 5
مثال للكائنات
String x="i am ahmed";
String testMethod(String par){
par = "i am not ahmed";
retunr par;
}
فلو قمنا بالاستدعاءات فلن تحصل إلا على مثل نتائج المثال الأول اي لا تغير على قيمة المتغير العام لأنك مررت قيمته فقط
صراحة انا كنت في الباسكال وكان التمرير بال reference مفيدا جدا ولقد افتقدته في الجافا ولكن يوجد حلان
1-أن تسند الدالة إلى المتغير
مثال
ٍ String x = testMethod();
2-بعض الكائنات تحتوي على دوال للتعديل مثل الدال append في الكلاس StringBuilder
صحيح، الذي حصل هو انه مرر قيمة ال reference وهي address وبالتالي ال argument يؤشر لنفس الموقع، وبالتالي تستطيع تغيير قيمة ذلك الكائن لأن لديك reference أخر له، ولكن هناك بعض الكائنات تكون Immutable لا تتغير (لا يوجد اي setter لتغيير القيمة) وبالتالي لن تستطيع تغيير قيمة ذلك الكائن سواء كان ذلك بالمؤشر الأول أو الأخر..
حتى الكائنات ليس هناك طريقة لتغييرها إذا تم تمريرها إلى دالة كبراميتر. فقط يتم تغيير ماتؤشر إليه إذا تمت تهيئتها مسبقاً،
في هذا المثال يتم استقبال كان من نوع MyTest ثم يتم عمل instantiation له، لكن عند مناداة الكائن خارج الدالة نجد أنه مازال null
public static void main(String[] args) {
MyTest test = null;
setName(test);
System.out.println(test.name); // This generates NullPointerException
}
public static void setName(MyTest atest){
atest = new MyTest();
atest.id = 10;
atest.name = "Motaz";
}
الطريقة الوحيدة إذا كان هُناك أكثر من مُخرج هي تعريف كلاس للمعلومات التي نُريد إرجاعها في الدالة.
ليس مزعج، عند التغيير من لغة برمجة إلى لغة أخرى لابد من تغيير طريقة التفكير في حل المشاكل. استخدام الـ calling by reference هو سريع لأشياء البسيطة، لكن مع مرور الزمن وكثرة الاعتماد عليه يجعل الكود أقل مقروئية، وأقل فهماً، ويمكن أن يحدث خلط لدى المبرمج في نداء دوال تحتوي على باراميتر يتم استدعائه by reference، فيتسائل دائماً، هل يقوم بتهيئة هذا المتغير أم لا، وهل يقوم بوضع ثابت أم لابد من متغيير، وتكون المشكلة أكبر عند نداء دوال لمكتبات قام بكتابتها مبرمجيين آخرين، وتكون في أسواء حالاتها عند استخدامها مع خدمات الويب Web services والتي يتم استدعائها من أي لغة برمجة. لذلك لغة جافا استغنت من كل هذا الخلط حتى تكون اللغة نظيفة.
هذا رابط من اوراكل نفسها حول تمرير البارميترات في جافا
التعليقات