JavaRush /وبلاگ جاوا /Random-FA /اتوباکسینگ و جعبه گشایی در جاوا
Viacheslav
مرحله

اتوباکسینگ و جعبه گشایی در جاوا

در گروه منتشر شد
<h2>مقدمه</h2>یک زبان برنامه نویسی، مانند زبانی که مردم به آن صحبت می کنند، زندگی می کند و تغییر می کند، پدیده های جدیدی در آن ظاهر می شود تا استفاده از زبان را راحت تر کند. و همانطور که می دانیم، زبان باید به راحتی افکار ما را بیان کند.
اتوباکسینگ و جعبه گشایی در جاوا - 1
بنابراین، در جاوا SE 5، مکانیسم بوکس / جعبه گشایی معرفی شد. و یک آموزش جداگانه از Oracle به ویژگی های این وسیله برای بیان افکار اختصاص داده شده است: Autoboxing و Unboxing . <h2> بسته بندی خودکار بوکس</h2> بیایید به نمونه ای از بوکس بسته بندی خودکار نگاه کنیم. ابتدا بیایید ببینیم چگونه کار می کند. بیایید از سایت compilejava.net استفاده کنیم و یک کلاس ایجاد کنیم:
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 فایل کلاس کامپایل شده برای کلاس شما است. مطالبی مانند این را خواهیم دید:
اتوباکسینگ و جعبه گشایی در جاوا - 2
این همان «بایت کد» بدنام است. اما آنچه در حال حاضر برای ما مهم است آنچه می بینیم است. ابتدا 8080 اولیه روی پشته اجرای متد قرار می گیرد و سپس Integer.valueOf اجرا می شود . این "جادوی" بوکس است. و داخل ماژیک به این شکل است:
اتوباکسینگ و جعبه گشایی در جاوا - 3
یعنی در اصل، بسته به مقدار عدد، یک مورد جدید از حافظه نهان گرفته می شود 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 است . اگر به بایت کد نگاه کنیم به این صورت است:
اتوباکسینگ و جعبه گشایی در جاوا - 4
ظاهرا هیچ جادویی وجود ندارد. همه چیز در جاوا است. این فقط "به خودی خود" کار می کند. برای راحتی ما. <h2>راک</h2>
اتوباکسینگ و جعبه گشایی در جاوا - 5
هر ابزاری، اگر نادرست استفاده شود، به یک سلاح مهیب علیه خود تبدیل می شود. و مکانیسم بوکس / جعبه گشایی خودکار در جاوا نیز از این قاعده مستثنی نیست. اولین مقایسه واضح از طریق ==. من فکر می کنم این واضح است، اما اجازه دهید دوباره به آن نگاه کنیم:
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 فراخوانی می شود که آرایه ای از کاراکترها را از عدد می سازد. باز هم بدون جادو، فقط جاوا). بنابراین در هر شرایط نامشخصی، فقط باید به اجرا نگاه کرد و حداقل چیزی سر جای خود قرار می‌گیرد. #ویاچسلاو
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION