JavaRush /Java Blog /Random-TK /Java-da awtobokslamak we gutulmak
Viacheslav
Dereje

Java-da awtobokslamak we gutulmak

Toparda çap edildi
<h2> Giriş </h2> Programmirleme dili, adamlaryň gürleýän dili, ýaşaýşy we üýtgemegi ýaly, dil ulanmagy has amatly etmek üçin onda täze hadysalar peýda bolýar. Bilşimiz ýaly dil pikirlerimizi aňsatlyk bilen beýan etmeli.
Автоупаковка и распаковка в Java - 1
Şeýlelik bilen, Java SE 5-de boks / gutujy mehanizm girizildi. Oracle-dan aýratyn bir sapak, pikirleri beýan etmegiň bu serişdeleriniň aýratynlyklaryna bagyşlanýar: Awtobokslamak we açmak . <h2> Awto-gaplaýyş boksy </h2> Geliň, awto-gaplaýan boksyň mysalyna seredeliň. Ilki bilen, onuň nähili işleýändigini göreliň. Compilejava.net sahypasyny ulanalyň we synp döredeliň:
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);
    }
}
Pleönekeý kod. Giriş parametrini kesgitläp, port bahasyny üýtgedip bileris. Görşümiz ýaly, sebäbi portuň bahasyny parametrlerden okaýarys String, Integerony geçip alýarys Integer.valueOf. Şonuň üçin biz ony başlangyç görnüş hökmünde däl-de, obýekt görnüşi hökmünde kesgitlemäge mejbur bolýarys Integer. Ine, bir tarapdan, obýekt üýtgeýjimiz bar, deslapky baha başlangyç. Bu işleýär. Emma jadylara ynanamzok, şeýlemi? Geliň, olaryň aýdyşy ýaly “kapotyň aşagyna” seredeliň. Çeşme koduny “ZIP ýüklemek” düwmesine basyp, compilejava.net-den göçürip alyň. Ondan soň göçürilen arhiwi kataloga çykaryň we oňa geçiň. Indi edeliň: javap -c -p App.classbu ýerde App.class synpyňyz üçin düzülen synp faýlydyr. Munuň ýaly mazmuny göreris:
Автоупаковка и распаковка в Java - 2
Bu şol bir meşhur “bytekod”. Emma indi biziň üçin möhüm zat görýänlerimizdir. Ilki bilen 8080 başlangyç usuly ýerine ýetiriş stakasyna ýerleşdirilýär, soň bolsa Integer.valueOf ýerine ýetirilýär . Bu boksyň “jadysy”. Jadygöýüň içinde şeýle görünýär:
Автоупаковка и распаковка в Java - 3
.Agny, aslynda, keşiň bahasyna baglylykda täze keş alynar Integerýa-da keşden alynar (keş keşi diňe Integers massiwinden başga zat däl). IntegerElbetde, Integerdiňe bir beýle bagtly däldi. Baglanyşykly başlangyç görnüşleriň we olaryň örtükleriniň doly sanawy bar (OOP dünýäsinde ilkinjileri görkezýän synplar). Bu sanaw Oracle-dan Tutorial-yň iň aşaky böleginde berilýär: “ Awtobokslamak we gutulmak ”. Ilkinjilerden ýasalan massiwleriň üçünji tarap kitaphanalaryny birikdirmezden “örtüginiň” ýokdugyny derrew bellemelidiris. Bular. bizden Arrays.asListýasamaz . _ <h2> Blokdan çykarmak </h2> Boksyň tersine prosesi gutusyz gutusyna diýilýär. Açylýan mysala seredeliň: 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.absdiňe başlangyçlary kabul edýär. Näme etmeli? Örtük synpynda bu başlangyç üçin ýönekeý bir usul bar. Mysal üçin, bu intValueInteger usulydyr . Baýtkoda seretsek, bu şeýle:
Автоупаковка и распаковка в Java - 4
Görşüňiz ýaly jady ýok. Hemme zat Java-da. Diňe “özi” işleýär. Amatlylygymyz üçin. <h2> Rake </h2>
Автоупаковка и распаковка в Java - 5
Любой инструмент при неправильном использовании становится грозным оружием против самого себя. И механизм автоупаковка и распаковка boxing/unboxing в 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
}
В первом случае, meaning берётся из кэша Integer значений (см. объяснение Boxing выше), а во втором случае будет создаваться каждый раз новый an object. Но тут стоит оговориться. Это поведение зависит от верхней границы кэша (java.lang.Integer.IntegerCache.high). Кроме того, эта граница может измениться и из-за других настроек. На эту тему можно ознакомиться с обсуждением на stackoverflow: How large is the Integer cache? Естественно, an objectы нужно сравнивать через equals: System.out.println(notInCache.equals(notInCache2)); Вторая проблема, связанная с этим же механизмом – производительность. Любая упаковка в Java равносильна созданию нового an object. Если число не входит в значения из кэша (т.е. в -128 до 127), то будет каждый раз создаваться новый an object. Если вдруг упаковка (т.е. boxing) будет производиться в цикле, это вызовет огромный прирост ненужных an objectов и потребление ресурсов на работу сборщика мусора. Поэтому, не стоит слишком безрассудно относится к этому. Третьи не менее больные грабли вытекают из того же механизма:
public static void check(Integer value) {
    if (value <= 0) {
        throw new IllegalStateException("Value is too small");
    }
}
В этом codeе человек явно пытался не пройти мимо ошибки. Но тут нет проверки на null. Если на вход придёт null, то instead of понятной ошибки мы получим невнятный NullPointerException. Потому что для сравнения Java попробует выполнить value.intValue и свалится, т.к. value будет null. <h2>Вывод</h2>Механизм boxing/unboxing позволяет программисту писать меньше codeа и даже порой не думать о преобразовании из примитивов в an objectы и обратно. Но это не значит, что нужно забывать, How это работает. Иначе можно допустить ошибку, которая может всплыть не сразу. Не стоит полагаться на части системы, которые не fully под нашим контролем (How например граница integer). Но и не стоит забывать про все преимущества классов-обёрток (вроде 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'));
}
Так же правильный вывод из всего - нет магии, есть Howая-то реализация. И не везде будет всегда то, что мы ожидаем. Например тут нет упаковки: System.out.println("The number is " + 8); Пример выше компилятором будет соптимизирован в одну строку. То есть словно вы написали «The number is 8». И в примере ниже тоже не будет упаковки:
public static void main(String[] args) {
    System.out.println("The number is " + Math.abs(-2));
}
Как же так, когда у нас println принимает на вход an object и нужно How-то соединить строки. Строки… да, именно поэтому нет упаковки, How таковой. У Integer есть статические методы, но некоторые из них уровня package. То есть мы их не можем использовать, а вот в самой Java они могут активно использоваться. Вот тут How раз такой случай. Будет вызван метод getChars, который из числа делает массив символов. Опять же, ниHowой магии, только Java ). Так что в любой непонятной ситуации стоит просто посмотреть реализацию и хоть что-то да встанет на свои места. #Viacheslav
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION