ممکن است بدانید که جاوا از ارزش عبور می کند، اما به درک دلیل کمک می کند. در اینجا آنچه اتفاق می افتد زمانی که شما ارجاعات شیء قابل تغییر و تغییر ناپذیر را در جاوا ارسال می کنید، اتفاق می افتد.
- ارجاع اشیاء در جاوا
- «گذر بر اساس مرجع» و «گذر بر اساس مقدار» تعریف شده است< /li>
- ارجاعات شی جاوا با مقدار ارسال می شوند
- گذراندن انواع اولیه در جاوا
- ارسال ارجاعات شیء تغییرناپذیر در جاوا
- ارسال ارجاعات شیء قابل تغییر در جاوا
- خلاصه آنچه آموختهاید
- آنچه را در مورد ارجاعات اشیا آموختهاید آزمایش کنید
- درباره جاوا بیشتر بیاموزید
بسیاری از زبانهای برنامهنویسی اجازه میدهند اشیاء را با مرجع یا مقدار ارسال کنند. در جاوا، ما فقط میتوانیم پارامترهای شی را براساس مقدار ارسال کنیم. این محدودیت ها را تحمیل می کند و همچنین سؤالاتی را ایجاد می کند. به عنوان مثال، اگر مقدار پارامتر در متد تغییر کند، پس از اجرای متد چه اتفاقی برای مقدار می افتد؟ همچنین ممکن است تعجب کنید که جاوا چگونه مقادیر شی را در پشته حافظه مدیریت می کند. این مقاله به شما کمک میکند این سؤالات رایج و سایر سؤالات رایج در مورد ارجاعات شی در جاوا را حل کنید.
ارجاع اشیا در جاوا
در این مقاله شما تفاوت بین عبور از طریق مرجع و عبور از مقدار در جاوا و نحوه ارسال ارجاعات شی جاوا را خواهید آموخت:
- «گذر از طریق مرجع» و «گذر بر اساس مقدار» تعریف شده است
- ارجاعات شی جاوا با مقدار ارسال می شوند
- گذراندن انواع اولیه در جاوا
- ارسال ارجاعات شیء تغییرناپذیر در جاوا
- ارسال ارجاعات شیء قابل تغییر در جاوا
- هنگام ارسال ارجاعات اشیا از چه چیزهایی باید اجتناب کرد
- چه چیزهایی را در مورد انتقال ارجاعات شیء به خاطر بسپارید
«عبور با مرجع» و «گذر بر اساس مقدار» تعریف شده است
Pass by مرجع به این معنی است که مکانی را در حافظه که مقدار متغیر در آن ذخیره میشود ارسال میکنیم و pass by value به این معنی است که یک کپی از مقدار واقعی متغیر را ارسال میکنیم. البته کمی پیچیده تر از آن است، اما این تعریف نقطه شروع خوبی است.
- گذر از مقدار به این معنی است که ما یک کپی از مقدار را ارسال می کنیم.
- عبور از طریق مرجع به این معنی است که ما مرجع واقعی را به متغیر موجود در حافظه منتقل میکنیم.
ارجاعات شی جاوا با مقدار ارسال می شوند
همه ارجاعات شیء در جاوا با مقدار ارسال می شوند. این بدان معنی است که یک کپی از مقدار به یک متد ارسال می شود. بخش مشکل این است که ارسال یک کپی از مقدار، ارزش واقعی شی را تغییر می دهد. این مثال باید به شما کمک کند تا بفهمید چرا:
public class ObjectReferenceExample {
public static void main(String... doYourBest) {
Simpson simpson = new Simpson();
transformIntoHomer(simpson);
System.out.println(simpson.name);
}
static void transformIntoHomer(Simpson simpson) {
simpson.name = "Homer";
}
}
class Simpson {
String name;
}
به نظر شما simpson.name
پس از اجرای متد transformIntoHomer
چه خواهد بود؟
در این صورت، هومر خواهد بود! دلیل آن این است که متغیرهای شی جاوا به سادگی ارجاعی هستند که به اشیاء واقعی در پشته حافظه اشاره می کنند. بنابراین، حتی اگر جاوا پارامترها را بر اساس مقدار به متدها ارسال می کند، اگر متغیر به یک مرجع شی اشاره کند، شی واقعی نیز تغییر می کند.
اگر هنوز مطمئن نیستید که چگونه کار می کند، نمودار زیر را در نظر بگیرید:
گذراندن انواع اولیه در جاوا
مانند انواع شی، انواع اولیه نیز با مقدار ارسال می شوند. آیا می توانید حدس بزنید چه اتفاقی برای انواع اولیه در مثال کد زیر می افتد؟
public class PrimitiveByValueExample {
public static void main(String... primitiveByValue) {
int homerAge = 30;
changeHomerAge(homerAge);
System.out.println(homerAge);
}
static void changeHomerAge(int homerAge) {
homerAge = 35;
}
}
اگر تشخیص داده اید که مقدار به ۳۰ تغییر می کند، درست می گویید. ۳۰ است زیرا (دوباره) جاوا پارامترهای شی را بر اساس مقدار ارسال می کند. عدد ۳۰ فقط یک کپی از مقدار است، نه مقدار واقعی. انواع اولیه در حافظه پشته تخصیص داده می شود، بنابراین فقط مقدار محلی تغییر خواهد کرد. در این مورد، هیچ مرجع شی وجود ندارد.
کد منبع را دریافت کنید
کد این مقاله را دریافت کنید. شما می توانید تست های خود را در حالی که از مثال ها پیروی می کنید، اجرا کنید.
ارسال ارجاعات شیء تغییرناپذیر در جاوا
اگر همان آزمایش را با یک شیء تغییرناپذیر String
انجام دهیم چه؟ توجه کنید وقتی مقدار رشته
:
را تغییر میدهیم چه اتفاقی میافتد
public class StringValueChange {
public static void main(String... doYourBest) {
String name = "";
changeToHomer(name);
System.out.println(name);
}
static void changeToHomer(String name) {
name = "Homer";
}
}
به نظر شما خروجی چه خواهد بود؟ اگر “” را حدس زدید، به شما تبریک می گویم! این به این دلیل است که یک شی String
تغییرناپذیر است، به این معنی که فیلدهای داخل String
نهایی هستند و قابل تغییر نیستند.
تغییرناپذیر کردن کلاس String
به ما کنترل بهتری بر یکی از پرکاربردترین اشیاء جاوا میدهد. اگر مقدار رشته
قابل تغییر باشد، باگ های زیادی ایجاد می کند. همچنین توجه داشته باشید که ما یک ویژگی از کلاس String
را تغییر نمی دهیم. در عوض، ما به سادگی یک مقدار String
جدید به آن اختصاص می دهیم. در این حالت، مقدار “Homer” به name
در روش changeToHomer
ارسال می شود. به محض اینکه روش changeToHomer
اجرا شد، String
“Homer” واجد شرایط جمعآوری زباله خواهد بود. حتی اگر شی را نمی توان تغییر داد، متغیر محلی خواهد بود.
ارسال ارجاعات شیء قابل تغییر در جاوا
برخلاف String
، بیشتر اشیا در JDK قابل تغییر هستند، مانند کلاس StringBuilder
. مثال زیر شبیه نمونه قبلی است، اما ویژگی StringBuilder
را به جای String
دارد:
static class MutableObjectReference {
public static void main(String... mutableObjectExample) {
StringBuilder name = new StringBuilder("Homer ");
addSureName(name);
System.out.println(name);
}
static void addSureName(StringBuilder name) {
name.append("Simpson");
}
}
آیا می توانید خروجی این مثال را حدس بزنید؟ در این حالت، چون ما با یک شیء قابل تغییر کار می کنیم، خروجی «Homer Simpson» خواهد بود. میتوانید از هر شیء تغییرپذیر دیگری در جاوا انتظار رفتار مشابهی داشته باشید.
خلاصه آنچه آموخته اید
شما آموخته اید که اشیاء جاوا با مقدار ارسال می شوند، به این معنی که یک کپی از مقدار ارسال می شود. فقط به یاد داشته باشید که مقدار کپی شده به یک شیء واقعی در پشته حافظه جاوا اشاره می کند. همچنین، به یاد داشته باشید که عبور از مقدار، مقدار شی واقعی را تغییر می دهد.
از چه چیزهایی باید هنگام ارسال ارجاعات شی جاوا اجتناب کرد
- سعی نکنید یک مقدار تغییرناپذیر را با مرجع تغییر دهید.
- سعی نکنید یک متغیر اولیه را با مرجع تغییر دهید.
- انتظار نداشته باشید با تغییر پارامتر شیء قابل تغییر در یک متد، شی واقعی تغییر نکند (تغییر خواهد کرد).
چه چیزهایی را در مورد ارسال ارجاعات شی جاوا به خاطر بسپارید
- جاوا همیشه متغیرهای پارامتر را بر اساس مقدار ارسال می کند.
- متغیرهای شی در جاوا همیشه به شی واقعی در پشته حافظه اشاره می کنند.
- مقدار یک شیء قابل تغییر زمانی که به یک متد ارسال می شود قابل تغییر است.
- مقدار یک شیء تغییرناپذیر قابل تغییر نیست، حتی اگر مقدار جدیدی به آن ارسال شود.
آنچه را در مورد ارجاعات شیء آموخته اید آزمایش کنید
اکنون، بیایید آنچه را که در مورد ارجاعات اشیا آموختهاید، آزمایش کنیم. در مثال کد زیر، کلاس String
غیرقابل تغییر و StringBuilder
قابل تغییر را مشاهده می کنید. هر کدام به عنوان یک پارامتر به یک متد ارسال می شود. با دانستن اینکه جاوا فقط از مقدار عبور می کند، فکر می کنید پس از اجرای متد اصلی از این کلاس، خروجی چه خواهد بود؟
public class DragonWarriorReferenceChallenger {
public static void main(String... doYourBest) {
StringBuilder warriorProfession = new StringBuilder("Dragon ");
String warriorWeapon = "Sword ";
changeWarriorClass(warriorProfession, warriorWeapon);
System.out.println("Warrior=" + warriorProfession + " Weapon=" + warriorWeapon);
}
static void changeWarriorClass(StringBuilder warriorProfession, String weapon) {
warriorProfession.append("Knight");
weapon = "Dragon " + weapon;
weapon = null;
warriorProfession = null;
}
}
در اینجا گزینهها وجود دارد، برای پاسخ، انتهای مقاله را بررسی کنید.
A: Warrior=null Weapon=null
B: Warrior=Dragon Weapon=Dragon
C: Warrior=Dragon Knight Weapon=Dragon Sword
D: Warrior=Dragon Knight Weapon =شمشیر
حل چالش
اولین پارامتر در مثال بالا، متغیر warriorProfession
است که یک شیء قابل تغییر است. پارامتر دوم، سلاح، یک رشته
تغییرناپذیر است:
static void changeWarriorClass(StringBuilder warriorProfession, String weapon) {
...
}
در خط اول این روش، مقدار Knight
را به متغیر warriorProfession
اضافه میکنیم. به یاد داشته باشید که warriorProfession
یک شیء قابل تغییر است. بنابراین شی واقعی تغییر خواهد کرد و مقدار آن “شوالیه اژدها” خواهد بود.
warriorProfession.append("Knight");
در دستورالعمل دوم، متغیر محلی غیرقابل تغییر String
به “شمشیر اژدها” تغییر خواهد کرد. با این حال، شی واقعی هرگز تغییر نخواهد کرد، زیرا String
تغییر ناپذیر است و ویژگی های آن نهایی هستند:
weapon = "Dragon " + weapon;
در نهایت، null
را به متغیرهای اینجا میدهیم، اما به آبجکتها نمیدهیم. تا زمانی که اشیاء از خارج قابل دسترسی باشند – در این مورد از طریق روش اصلی – یکسان خواهند ماند. و اگرچه متغیرهای محلی تهی خواهند بود، اما هیچ اتفاقی برای اشیاء نخواهد افتاد:
weapon = null;
warriorProfession = null;
از اینجا میتوان نتیجه گرفت که مقادیر نهایی StringBuilder
و String
غیرقابل تغییر ما خواهد بود:
System.out.println("Warrior=" + warriorProfession + " Weapon=" + warriorWeapon);
تنها مقداری که در روش changeWarriorClass
تغییر کرد warriorProfession
بود، زیرا یک شیء StringBuilder
قابل تغییر است. توجه داشته باشید که warriorWeapon
تغییری نکرده است زیرا یک شیء String
تغییرناپذیر است.
خروجی صحیح کد Challenger ما خواهد بود:
D: Warrior=Dragon Knight Weapon=Sword
.
چالش ویدیویی! اشکال زدایی ارجاعات شی در جاوا
اشکالزدایی یکی از سادهترین راهها برای جذب کامل مفاهیم برنامهنویسی و در عین حال بهبود کد شماست. در این ویدیو، میتوانید در حین اشکالزدایی و توضیح مراجع شی در جاوا، همراه باشید.
درباره جاوا بیشتر بیاموزید
- نکات کد سریع بیشتری دریافت کنید: همه مقالات رافائل را در مجموعه چالشگران جاوا InfoWorld بخوانید.
- ویدیوهای بیشتر را در لیست پخش ویدیوی جاوا Challengers رافائل ببینید .
- در وبلاگ چالشگران جاوا رافائل و در کتاب او، جاوا چلنجرهای بیشتری را با بیش از ۷۰ چالش کد.
پست های مرتبط
آیا جاوا با مرجع عبور می کند یا با مقدار عبور می کند؟
آیا جاوا با مرجع عبور می کند یا با مقدار عبور می کند؟
آیا جاوا با مرجع عبور می کند یا با مقدار عبور می کند؟