JavaRush /Java блогы /Random-KK /Java тіліндегі автобокс және қораптан шығару
Viacheslav
Деңгей

Java тіліндегі автобокс және қораптан шығару

Топта жарияланған
<h2>Кіріспе</h2>Бағдарламалау тілі, адамдар сөйлейтін, өмір сүретін және өзгертетін тіл сияқты, тілді қолдануды ыңғайлы ету үшін онда жаңа құбылыстар пайда болады. Ал біз білетіндей, тіл біздің ойымызды ыңғайлы түрде білдіруі керек.
Java тіліндегі автобокс және қораптан шығару - 1
Сонымен, Java 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);
    }
}
Қарапайым code. Біз енгізу параметрін көрсетіп, порт мәнін өзгерте аламыз. Көріп отырғанымыздай, өйткені біз параметрлерден порт мәнін оқимыз , оны арқылы алу арқылы Stringаламыз . Сондықтан біз оны қарабайыр тип ретінде емес, нысан түрі ретінде көрсетуге мәжбүрміз . Міне, бір жағынан, бізде an objectінің айнымалысы бар, ал әдепкі мән - қарабайыр. Және ол жұмыс істейді. Бірақ біз сиқырға сенбейміз, солай ма? Олар айтқандай, «қапшық астына» назар аударайық. «ZIP жүктеп алу» түймесін басу арқылы compilejava.net сайтынан бастапқы codeты жүктеп алыңыз. Осыдан кейін жүктелген мұрағатты каталогқа шығарып, оған өтіңіз. Енді мынаны орындаймыз: мұнда App.class - сынып үшін құрастырылған сынып файлы. Біз келесідей мазмұнды көреміз: IntegerInteger.valueOfIntegerjavap -c -p App.class
Java тіліндегі автобокс және қораптан шығару - 2
Бұл бірдей атышулы «bytecode». Бірақ қазір біз үшін маңыздысы - біз не көреміз. Алдымен, 8080 примитиві әдісті орындау стекіне орналастырылады, содан кейін Integer.valueOf орындалады . Бұл бокстың «сиқыры». Ал сиқырдың ішкі көрінісі келесідей:
Java тіліндегі автобокс және қораптан шығару - 3
Яғни, мәні бойынша, жаңасы кэштен алынады Integerнемесе алынады (кэш тек бүтін сандар массивінен басқа ештеңе емес) санның мәніне байланысты. IntegerӘрине, Integerмұндай бақыт бір ғана емес. Қатысты қарабайыр типтердің және олардың орауыштарының толық тізімі бар (OOP әлеміндегі примитивтерді көрсететін сыныптар). Бұл тізім Oracle оқулығының ең төменгі жағында берілген: « Автобокс және қораптан шығару ». Қарапайым элементтерден жасалған массивтерде үшінші тарап кітапханаларын қоспай-ақ «орама» жоқ екенін бірден атап өткен жөн. Анау. -дан біз үшін Arrays.asListжасамайды . <h2>Қораптан шығару</h2>Боксқа кері процесс қораптан шығару деп аталады. Қаптаманы ашу мысалын қарастырайық: 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.absтек примитивтерді қабылдайды. Енді не істеу керек? Қаптама класында бұл жағдай үшін қарабайыр мәнді қайтаратын арнайы әдіс бар. Мысалы, бұл intValueInteger әдісі . Егер біз byte codeты қарасақ, ол келесідей:
Java тіліндегі автобокс және қораптан шығару – 4
Көріп отырғаныңыздай, сиқыр жоқ. Барлығы Java ішінде. Ол жай ғана «өздігінен» жұмыс істейді. Біздің ыңғайлылығымыз үшін. <h2>Тырма</h2>
Java тіліндегі автобокс және қораптан шығару - 5
Кез келген құрал, егер дұрыс пайдаланылмаса, өзіне қарсы күшті қаруға айналады. Java-дағы автоматты бокс/бокс ашу механизмі де ерекшелік емес. Бірінші, айқын салыстыру арқылы ==. Менің ойымша, бұл түсінікті, бірақ оны қайтадан қарастырайық:
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 бойынша оқуға болады: Бүтін кэш қаншалықты үлкен? Әрине, an objectілерді теңдік арқылы салыстыру қажет: System.out.println(notInCache.equals(notInCache2)); Бірдей механизммен байланысты екінші мәселе өнімділік болып табылады. Java тіліндегі кез келген бокс жаңа нысан жасаумен бірдей. Егер нөмір кэш мәндеріне қосылмаса (яғни -128-ден 127-ге дейін), әр жолы жаңа нысан жасалады. Егер кенеттен орау (яғни бокс) циклде орындалса, бұл қажетсіз заттардың үлкен өсуіне және қоқыс жинағыштың жұмысы үшін ресурстарды тұтынуға әкеледі. Сондықтан бұл туралы тым абай болмаңыз. Үшінші, кем емес ауыртпалық бір механизмнен туындайды:
public static void check(Integer value) {
    if (value <= 0) {
        throw new IllegalStateException("Value is too small");
    }
}
Бұл codeта адам қатені айналып өтпеуге тырысты. Бірақ тексеру жоқ null. Егер бұл кіріске келетін болса null, онда түсінікті қатенің орнына түсініксіз қатені аламыз NullPointerException. Салыстыру үшін Java орындауға тырысады value.intValueжәне бұзылады, себебі... valueболады null. <h2>Қорытынды</h2>Қорытынды/қорытындылау механизмі бағдарламашыға аз code жазуға мүмкіндік береді және кейде тіпті қарабайырлардан an objectілерге және кері түрлендіру туралы ойламайды. Бірақ бұл оның қалай жұмыс істейтінін ұмыту керек дегенді білдірмейді. Әйтпесе, сіз бірден пайда болмайтын қателік жібере аласыз. Жүйенің толық бақылауымызда болмайтын бөліктеріне (мысалы, бүтін сан шекарасы) сенбеу керек. Бірақ орауыш сыныптарының барлық артықшылықтары туралы ұмытпаңыз (мысалы Integer). Көбінесе бұл орауыш сыныптарында сіздің өміріңізді жақсартатын және codeыңызды мәнерлі ететін қосымша статикалық әдістер жиынтығы болады. Төмендегі мысал:
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Біз an objectіні кіріс ретінде қабылдағанда және қандай да бір жолмен сызықтарды қосу керек болғанда, бұл қалай болуы мүмкін . Сызықтар... иә, сондықтан мұндай қаптама жоқ. Статикалық әдістер бар Integer, бірақ олардың кейбіреулері package. Яғни, біз оларды пайдалана алмаймыз, бірақ Java-ның өзінде оларды белсенді түрде қолдануға болады. Бұл жерде дәл солай. GetChars әдісі шақырылады, ол саннан таңбалар массивін жасайды. Тағы да, сиқыр жоқ, тек Java). Сондықтан кез келген түсініксіз жағдайда сіз жай ғана іске асыруды қарауыңыз керек және кем дегенде бір нәрсе орнына түседі. #Вячеслав
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION