<h2>مقدمه</h2>یک زبان برنامه نویسی، مانند زبانی که مردم به آن صحبت می کنند، زندگی می کند و تغییر می کند، پدیده های جدیدی در آن ظاهر می شود تا استفاده از زبان را راحت تر کند. و همانطور که می دانیم، زبان باید به راحتی افکار ما را بیان کند.
بنابراین، در جاوا SE 5، مکانیسم بوکس / جعبه گشایی معرفی شد. و یک آموزش جداگانه از Oracle به ویژگی های این وسیله برای بیان افکار اختصاص داده شده است: Autoboxing و Unboxing . <h2> بسته بندی خودکار بوکس</h2> بیایید به نمونه ای از بوکس بسته بندی خودکار نگاه کنیم. ابتدا بیایید ببینیم چگونه کار می کند. بیایید از سایت compilejava.net استفاده کنیم و یک کلاس ایجاد کنیم:
این همان «بایت کد» بدنام است. اما آنچه در حال حاضر برای ما مهم است آنچه می بینیم است. ابتدا 8080 اولیه روی پشته اجرای متد قرار می گیرد و سپس Integer.valueOf اجرا می شود . این "جادوی" بوکس است. و داخل ماژیک به این شکل است:
یعنی در اصل، بسته به مقدار عدد، یک مورد جدید از حافظه نهان گرفته می شود
ظاهرا هیچ جادویی وجود ندارد. همه چیز در جاوا است. این فقط "به خودی خود" کار می کند. برای راحتی ما. <h2>راک</h2>
هر ابزاری، اگر نادرست استفاده شود، به یک سلاح مهیب علیه خود تبدیل می شود. و مکانیسم بوکس / جعبه گشایی خودکار در جاوا نیز از این قاعده مستثنی نیست. اولین مقایسه واضح از طریق
public class App {
public static void main(String[] args) {
Integer portNumber = 8080;
if (args.length != 0) {
portNumber = Integer.valueOf(args[0]);
}
System.out.println("Port number is: " + portNumber);
}
}
کد ساده می توانیم پارامتر ورودی را مشخص کرده و مقدار پورت را تغییر دهیم. همانطور که می بینیم، زیرا String
مقدار پورت را از روی پارامترها می خوانیم ، Integer
با دریافت آن به آن می رسیم Integer.valueOf
. بنابراین، ما مجبور هستیم که آن را نه به عنوان یک نوع اولیه، بلکه به عنوان یک نوع شی مشخص کنیم Integer
. و در اینجا ما از یک طرف، یک متغیر شی داریم، و مقدار پیش فرض یک اولیه است. و کار می کند. اما ما به جادو اعتقادی نداریم، نه؟ همانطور که می گویند، بیایید نگاهی به "زیر کاپوت" بیندازیم. با کلیک بر روی "دانلود ZIP" کد منبع را از compilejava.net دانلود کنید. پس از آن، آرشیو دانلود شده را در یک پوشه استخراج کرده و به آن بروید. حالا بیایید انجام دهیم: javap -c -p App.class
جایی که App.class فایل کلاس کامپایل شده برای کلاس شما است. مطالبی مانند این را خواهیم دید:
Integer
یا دریافت می شود Integer
(کش چیزی بیش از یک آرایه از اعداد صحیح نیست). طبیعتاً Integer
نه تنها یکی از آنها خوش شانس بود. فهرست کاملی از انواع ابتدایی مرتبط و بستهبندیهای آنها (کلاسهایی که نشاندهندههای اولیه در دنیای OOP هستند) وجود دارد. این لیست در انتهای آموزش اوراکل آورده شده است: " اتوباکسینگ و جعبه گشایی ". شایان ذکر است که آرایههای ساخته شده از ابتداییها بدون اتصال کتابخانههای شخص ثالث، دارای «پوشش» نیستند. آن ها Arrays.asList
نمی خواهد از int[]
برای ما List
از Integer
'س. <h2> جعبه گشایی</h2>فرآیند معکوس بوکس جعبه گشایی نامیده می شود. بیایید به یک مثال باز کردن بسته بندی نگاه کنیم:
public class App {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Please, enter params");
return;
}
int value = Math.abs(Integer.valueOf(args[0]));
System.out.println("Absolute value is: " + value);
}
}
Math.abs
فقط ابتدایی ها را می پذیرد. چه باید کرد؟ کلاس wrapper یک متد خاص برای این مورد دارد که یک primitive را برمی گرداند. به عنوان مثال، این Integer
روش intValue است . اگر به بایت کد نگاه کنیم به این صورت است:
==
. من فکر می کنم این واضح است، اما اجازه دهید دوباره به آن نگاه کنیم:
public static void main(String[] args) {
Integer inCacheValue = 127;
Integer inCacheValue2 = 127;
Integer notInCache = 128; // new Integer(129)
Integer notInCache2 = 128; // new Integer(129)
System.out.println(inCacheValue == inCacheValue2); //true
System.out.println(notInCache == notInCache2); //false
}
در حالت اول، مقدار از Integer
حافظه پنهان مقدار گرفته می شود (به توضیح Boxing در بالا مراجعه کنید)، و در حالت دوم هر بار یک شی جدید ایجاد می شود. اما در اینجا ارزش رزرو کردن را دارد. این رفتار به کران بالای کش بستگی دارد ( java.lang.Integer.IntegerCache.high ). علاوه بر این، این محدودیت ممکن است به دلیل تنظیمات دیگر تغییر کند. می توانید بحث در مورد این موضوع را در مورد stackoverflow بخوانید: حافظه پنهان عدد صحیح چقدر است؟ به طور طبیعی، اشیاء باید با استفاده از مساوی مقایسه شوند: System.out.println(notInCache.equals(notInCache2));
مشکل دوم مرتبط با مکانیسم یکسان عملکرد است. هر بوکس در جاوا معادل ایجاد یک شی جدید است. اگر عدد در مقادیر حافظه نهان گنجانده نشده باشد (یعنی -128 تا 127)، هر بار یک شی جدید ایجاد می شود. اگر به طور ناگهانی بسته بندی (یعنی بوکس) در یک حلقه انجام شود، این امر باعث افزایش چشمگیر اشیاء غیر ضروری و مصرف منابع برای کار زباله گرد می شود. بنابراین، در مورد آن بیش از حد بی پروا نباشید. سومین چنگک نه چندان دردناک از همین مکانیسم ناشی می شود:
public static void check(Integer value) {
if (value <= 0) {
throw new IllegalStateException("Value is too small");
}
}
در این کد، شخص به وضوح سعی می کرد از خطا عبور نکند. اما هیچ بررسی وجود ندارد null
. اگر به ورودی می رسد null
، به جای یک خطای قابل درک، یک خطای نامفهوم دریافت می کنیم NullPointerException
. زیرا برای مقایسه، جاوا سعی می کند اجرا value.intValue
و خراب شود، زیرا ... value
اراده null
. <h2>نتیجه گیری</h2>مکانیسم boxing/unboxing به برنامه نویس این امکان را می دهد که کد کمتری بنویسد و گاهی حتی به تبدیل از اولیه به اشیا و برگشت فکر هم نمی کند. اما این بدان معنا نیست که باید نحوه کارکرد آن را فراموش کنید. در غیر این صورت، ممکن است اشتباهی مرتکب شوید که ممکن است بلافاصله ظاهر نشود. ما نباید به بخش هایی از سیستم که کاملا تحت کنترل ما نیستند (مانند مرز عدد صحیح) تکیه کنیم. اما تمام مزایای کلاس های wrapper (مانند) را فراموش نکنید Integer
. اغلب این کلاسهای wrapper مجموعهای از روشهای ثابت اضافی دارند که زندگی شما را بهتر و کد شما را گویاتر میکنند. در اینجا یک مثال تکمیلی آورده شده است:
public static void main(String[] args) {
int first = 1;
int second = 5;
System.out.println(Integer.max(first, second));
System.out.println(Character.toLowerCase('S'));
}
نتیجه درست از همه چیز این است که جادو وجود ندارد، نوعی تحقق وجود دارد. و همیشه همه چیز آنطور که ما انتظار داریم نخواهد بود. به عنوان مثال، بسته بندی وجود ندارد: System.out.println("The number is " + 8);
مثال بالا توسط کامپایلر در یک خط بهینه می شود. یعنی مثل اینکه نوشته اید «عدد 8 است». و در مثال زیر هیچ بسته بندی نیز وجود نخواهد داشت:
public static void main(String[] args) {
System.out.println("The number is " + Math.abs(-2));
}
println
وقتی یک شی را به عنوان ورودی می گیریم و باید به نحوی خطوط را به هم وصل کنیم چطور ممکن است باشد . خطوط... بله، به همین دلیل است که هیچ بسته بندی وجود ندارد. روش های ایستا وجود Integer
دارد، اما برخی از آنها هستند package
. یعنی ما نمی توانیم از آنها استفاده کنیم، اما در خود جاوا می توان به طور فعال از آنها استفاده کرد. اینجا دقیقا همینطوره. متد getChars فراخوانی می شود که آرایه ای از کاراکترها را از عدد می سازد. باز هم بدون جادو، فقط جاوا). بنابراین در هر شرایط نامشخصی، فقط باید به اجرا نگاه کرد و حداقل چیزی سر جای خود قرار میگیرد. #ویاچسلاو
GO TO FULL VERSION