JavaRush /Java blogi /Random-UZ /Java-da avtobokslash va qutidan chiqarish
Viacheslav
Daraja

Java-da avtobokslash va qutidan chiqarish

Guruhda nashr etilgan
<h2>Kirish</h2>Dasturlash tili, odamlar so'zlashadigan, yashaydigan va o'zgarib turadigan til kabi unda yangi hodisalar paydo bo'lib, tildan foydalanish qulayroq bo'ladi. Va biz bilganimizdek, til bizning fikrlarimizni qulay tarzda ifodalashi kerak.
Java-da autoboxing va unboxing - 1
Shunday qilib, Java SE 5 da boxing/unboxing mexanizmi joriy etildi. Va Oracle-dan alohida o'quv qo'llanma ushbu fikrlarni ifodalash vositalarining xususiyatlariga bag'ishlangan: Autoboxing va Unboxing . <h2>Avtomatik qadoqlash boks</h2>Keling, boksni avtomatik qadoqlash misolini ko'rib chiqaylik. Birinchidan, keling, bu qanday ishlashini ko'rib chiqaylik. Keling, compilejava.net saytidan foydalanamiz va sinf yaratamiz:
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);
    }
}
Oddiy kod. Biz kirish parametrini belgilashimiz va port qiymatini o'zgartirishimiz mumkin. Ko'rib turganimizdek, chunki biz parametrlardan port qiymatini o'qiymiz , uni orqali olish orqali Stringolamiz . Shuning uchun biz uni ibtidoiy tur sifatida emas, balki ob'ekt turi sifatida ko'rsatishga majburmiz . Va bu erda biz, bir tomondan, ob'ekt o'zgaruvchiga ega bo'lamiz va standart qiymat ibtidoiydir. Va u ishlaydi. Lekin biz sehrga ishonmaymiz, shunday emasmi? Keling, ular aytganidek, "kaput ostida" ni ko'rib chiqaylik. “ZIP-ni yuklab olish” tugmasini bosish orqali compilejava.net saytidan manba kodini yuklab oling. Shundan so'ng, yuklab olingan arxivni katalogga olib tashlang va unga o'ting. Endi bajaramiz: bu erda App.class sizning sinfingiz uchun kompilyatsiya qilingan sinf faylidir. Biz shunday tarkibni ko'ramiz: IntegerInteger.valueOfIntegerjavap -c -p App.class
Java-da autoboxing va unboxing - 2
Bu bir xil mashhur "bayt-kod". Ammo hozir biz uchun muhim bo'lgan narsa biz ko'rayotgan narsadir. Birinchidan, 8080 ibtidoiy usulni bajarish stekiga joylashtiriladi va keyin Integer.valueOf bajariladi . Bu boksning "sehridir". Va sehrning ichida shunday ko'rinadi:
Java-da autoboxing va unboxing - 3
Ya'ni, mohiyatan, keshdan yangisi olinadi Integeryoki olinadi Integer(kesh faqat butun sonlar massividan boshqa narsa emas) raqamning qiymatiga qarab. Tabiiyki, Integerbunchalik omad faqat bitta emas edi. Tegishli ibtidoiy turlarning to'liq ro'yxati va ularning o'ramlari (OOP dunyosida ibtidoiylarni ifodalovchi sinflar) mavjud. Ushbu roʻyxat Oracle qoʻllanmasining eng quyi qismida keltirilgan: “ Autoboxing and Unboxing ”. Darhol shuni ta'kidlash kerakki, ibtidoiylardan tayyorlangan massivlarda uchinchi tomon kutubxonalarini ulamasdan "o'rash" yo'q. Bular. dan biz uchun Arrays.asListyaratmaydi . <h2>Unboxing</h2>Boksga teskari jarayon unboxing unboxing deb ataladi. Keling, ochish misolini ko'rib chiqaylik: int[]ListInteger
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.absfaqat primitivlarni qabul qiladi. Nima qilsa bo'ladi? O'rash sinfida bu holat uchun primitivni qaytaradigan maxsus usul mavjud. Masalan, bu intValueInteger usuli . Agar bayt kodiga qarasak, u quyidagicha bo'ladi:
Java-da autoboxing va unboxing - 4
Ko'rinib turibdiki, sehr yo'q. Hamma narsa Java ichida. U faqat "o'z-o'zidan" ishlaydi. Bizning qulayligimiz uchun. <h2>Rake</h2>
Java-da autoboxing va unboxing - 5
Har qanday vosita, agar noto'g'ri ishlatilsa, o'ziga qarshi dahshatli qurolga aylanadi. Va Java-dagi avtomatik boks / qutidan chiqarish mexanizmi bundan mustasno emas. Birinchi, aniq taqqoslash orqali amalga oshiriladi ==. Menimcha, bu aniq, lekin keling, yana bir bor ko'rib chiqaylik:
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
}
Birinchi holda, qiymat Integerqiymat keshidan olinadi (yuqoridagi Boxing tushuntirishiga qarang), ikkinchi holatda esa har safar yangi ob'ekt yaratiladi. Ammo bu erda bron qilish kerak. Bu xatti-harakatlar keshning yuqori chegarasiga bog'liq ( java.lang.Integer.IntegerCache.high ). Bundan tashqari, bu chegara boshqa sozlamalar tufayli o'zgarishi mumkin. Ushbu mavzu bo'yicha muhokamani stackoverflow bo'yicha o'qishingiz mumkin: Integer keshi qanchalik katta? Tabiiyki, ob'ektlarni tenglar yordamida solishtirish kerak: System.out.println(notInCache.equals(notInCache2)); Xuddi shu mexanizm bilan bog'liq ikkinchi muammo - bu ishlash. Java-dagi har qanday boks yangi ob'ekt yaratishga teng. Agar raqam kesh qiymatlariga kiritilmagan bo'lsa (ya'ni -128 dan 127 gacha), har safar yangi ob'ekt yaratiladi. Agar to'satdan qadoqlash (ya'ni, boks) halqada amalga oshirilsa, bu keraksiz narsalarning katta ko'payishiga va axlat yig'uvchining ishi uchun resurslarning sarflanishiga olib keladi. Shuning uchun, bu borada juda beparvo bo'lmang. Uchinchi, kamroq og'riqli rake bir xil mexanizmdan kelib chiqadi:
public static void check(Integer value) {
    if (value <= 0) {
        throw new IllegalStateException("Value is too small");
    }
}
Ushbu kodda odam xatodan o'tmaslikka harakat qilgani aniq. Lekin hech qanday tekshiruv yo'q null. Agar u kirishga keladigan bo'lsa null, unda tushunarli xato o'rniga biz tushunarsiz bo'lamiz NullPointerException. Taqqoslash uchun Java bajarishga harakat qiladi value.intValueva ishdan chiqadi, chunki... valuebo'ladi null. <h2>Xulosa</h2>Boks / qutidan chiqarish mexanizmi dasturchiga kamroq kod yozishga imkon beradi va ba'zan hatto ibtidoiylardan ob'ektlarga va orqaga o'tish haqida o'ylamaydi. Ammo bu uning qanday ishlashini unutishingiz kerak degani emas. Aks holda, siz darhol paydo bo'lmasligi mumkin bo'lgan xatoga yo'l qo'yishingiz mumkin. Biz tizimning to'liq nazoratimiz ostida bo'lmagan qismlariga (masalan, butun son chegarasi) tayanmasligimiz kerak. Lekin o'rash sinflarining barcha afzalliklari haqida unutmang (kabi Integer). Ko'pincha bu o'rash sinflari hayotingizni yaxshilaydigan va kodingizni yanada ifodali qiladigan qo'shimcha statik usullar to'plamiga ega. Mana bir misol:
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'));
}
Hamma narsadan to'g'ri xulosa shuki, sehr yo'q, qandaydir amalga oshirish bor. Va har doim ham hamma narsa biz kutgandek bo'lmaydi. Masalan, qadoqlash yo'q: System.out.println("The number is " + 8); Yuqoridagi misol kompilyator tomonidan bitta qatorga optimallashtiriladi. Ya'ni, go'yo siz "Raqam 8" deb yozgandeksiz. Quyidagi misolda ham qadoqlash bo'lmaydi:
public static void main(String[] args) {
    System.out.println("The number is " + Math.abs(-2));
}
printlnOb'ektni kirish sifatida qabul qilsak va qandaydir tarzda chiziqlarni ulashimiz kerak bo'lsa, bu qanday bo'lishi mumkin . Chiziqlar... ha, shuning uchun bunday qadoqlash yo'q. Statik usullar mavjud Integer, ammo ulardan ba'zilari package. Ya'ni, biz ulardan foydalana olmaymiz, lekin Java-ning o'zida ulardan faol foydalanish mumkin. Bu yerda aynan shunday. GetChars usuli chaqiriladi, bu raqamdan belgilar qatorini hosil qiladi. Shunga qaramay, sehr yo'q, faqat Java). Shunday qilib, har qanday noaniq vaziyatda siz faqatgina amalga oshirishga qarashingiz kerak va hech bo'lmaganda biror narsa joyiga tushadi. #Viacheslav
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION