JavaRush /Java блогы /Random-KK /Java тіліндегі қарабайыр типтер: олар соншалықты қарабайы...
Viacheslav
Деңгей

Java тіліндегі қарабайыр типтер: олар соншалықты қарабайыр емес

Топта жарияланған

Кіріспе

Қолданбаларды әзірлеуді кейбір деректермен жұмыс істеу, дәлірек айтқанда, оларды сақтау және өңдеу деп санауға болады. Бүгін мен бірінші негізгі аспектіге тоқталғым келеді. Java тілінде деректер қалай сақталады? Мұнда бізде екі ықтимал пішім бар: анықтамалық және қарапайым деректер түрлері. Қарапайым типтердің түрлері және олармен жұмыс істеу мүмкіндіктері туралы сөйлесейік (қандай десек те, бұл бағдарламалау тілі туралы біліміміздің негізі). Java қарабайыр деректер типтері барлығы тірек болатын негіз болып табылады. Жоқ, мен мүлдем асыра айтқан жоқпын. Oracle-да примитивтерге арналған жеке оқу құралы бар: Қарапайым деректер түрлері Java тіліндегі қарабайыр типтер: олар соншалықты қарабайыр емес - 1 Кішкене тарих. Басында нөл болды. Бірақ нөл қызықсыз. Содан кейін бит пайда болды . Неге олай аталды? Ол « bi nary digi t » (екілік сан) аббревиатурасынан осылай аталды . Яғни, оның екі ғана мағынасы бар. Ал ол нөл болғандықтан, қазір не 0, не 1 болуы қисынды. Ал өмір қызық болды. Биттер топ-тобымен жинала бастады. Ал бұл отарлар byte (byte) деп атала бастады . Қазіргі әлемде byte = 2 үшінші дәрежеге, яғни. 8. Бірақ бұл әрдайым бола бермейтіні белгілі болды. Байт атауының қайдан шыққаны туралы көптеген жорамалдар, аңыздар мен қауесеттер бар. Кейбіреулер мұның бәрі сол кездегі codeтаулар туралы деп ойлайды, ал басқалары ақпаратты осылай оқу тиімдірек деп санайды. Байт – жадтың ең кіші addressтелетін бөлігі. Бұл жадта бірегей мекенжайлары бар byteтар. ByTe – Binary Term – машина сөзінің аббревиатурасы деген аңыз бар. Машина сөзі - қарапайым тілмен айтқанда, бұл процессор бір операцияда өңдей алатын деректер көлемі. Бұрын машина сөзінің өлшемі ең кіші addressтік жадымен бірдей болды. Java тілінде айнымалылар тек byte мәндерін сақтай алады. Жоғарыда айтқанымдай, Java-да айнымалылардың екі түрі бар:
  • java қарабайыр түрлері деректер byteтарының мәнін тікелей сақтайды (осы примитивтердің түрлерін төменде толығырақ қарастырамыз);
  • сілтеме түрі, нысан мекенжайының byteтарын үймеде сақтайды, яғни осы айнымалылар арқылы біз an objectінің өзіне тікелей қол жеткіземіз (нысан үшін қашықтан басқару құралының түрі)

Java byteы

Сонымен, тарих бізге byte берді - біз пайдалана алатын жадтың ең аз көлемі. Және ол 8 биттен тұрады. Java-дағы ең кіші бүтін деректер түрі - byte. Бұл қол қойылған 8 биттік түрі. Бұл нені білдіреді? Есептеп көрейік. 2^8 - 256. Бірақ теріс сан алғымыз келсе ше? Ал Java әзірлеушілері «10000000» екілік codeы -128, яғни ең маңызды бит (ең сол жақ бит) санның теріс екенін көрсетеді деп шешті. Екілік «0111 1111» 127-ге тең. Яғни, 128-ді ешқандай жолмен белгілеуге болмайды, өйткені ол -128 болады. Толық есептеу мына жауапта берілген: Неліктен Java-да byte ауқымы -128-ден 127-ге дейін? Сандардың қалай алынғанын түсіну үшін суретке қарау керек:
Java тіліндегі қарабайыр типтер: олар соншалықты қарабайыр емес - 2
Тиісінше, өлшемін есептеу үшін 2^(8-1) = 128. Бұл ең төменгі шегі (және оның минусы бар) -128 болады дегенді білдіреді. Ал максимум 128 – 1 (нөлді алып тастаңыз). Яғни, максимум 127 болады. Шындығында, біз byte түрімен «жоғары деңгейде» жиі жұмыс істемейміз. Негізінен бұл «шикі» деректерді өңдеу. Мысалы, мәліметтерді желі арқылы тасымалдаумен жұмыс істегенде, деректер қандай да бір байланыс арнасы арқылы берілетін 0 және 1 жиыны болғанда. Немесе файлдардан деректерді оқу кезінде. Оларды жолдармен және codeтаулармен жұмыс істегенде де пайдалануға болады. Мысал code:
public static void main(String []args){
        byte value = 2;
        byte shortByteValue = 0b10; // 2
        System.out.println(shortByteValue);
        // Начиная с JDK7 мы можем разделять литералы подчёркиваниями
        byte minByteValue = (byte) 0B1000_0000; // -128
        byte maxByteValue = (byte) 0b0111_1111; // 127
        byte minusByteValue = (byte) 0b1111_1111; // -128 + 127
        System.out.println(minusByteValue);
        System.out.println(minByteValue + " to " + maxByteValue);
}
Айтпақшы, byte түрін пайдалану жад шығынын азайтады деп ойламаңыз. Байт негізінен деректерді массивтерде сақтау кезінде жадты тұтынуды азайту үшін қолданылады (мысалы, желі арқылы алынған деректерді byte массиві ретінде жүзеге асырылатын кейбір буферде сақтау). Бірақ деректермен операцияларды орындау кезінде byteты пайдалану сіздің күткеніңізге сәйкес келмейді. Бұл Java виртуалды машинасын (JVM) енгізумен байланысты. Көптеген жүйелер 32 немесе 64 бит болғандықтан, есептеулер кезінде byte пен қысқа 32 биттік интке түрлендіріледі, ол туралы кейінірек айтатын боламыз. Бұл есептеулерді жеңілдетеді. Қосымша мәліметтер алу үшін Байтты қосу java тілінің ережелері немесе jvm себебінен int түрлендіреді дегенді қараңыз. . Жауапта JLS (Java тілінің сипаттамасы) сілтемелері де бар. Сонымен қатар, byteты дұрыс емес жерде пайдалану ыңғайсыз сәттерге әкелуі мүмкін:
public static void main(String []args){
        for (byte i = 1; i <= 200; i++) {
            System.out.println(i);
        }
}
Мұнда цикл болады. Есептегіш мән максимумға (127) жеткендіктен, толып кету орын алады және мән -128 болады. Ал біз ешқашан циклден шыға алмаймыз.

қысқа

Байт мәндерінің шегі өте аз. Сондықтан келесі деректер түрі үшін біз бит санын екі есе көбейтуді шештік. Яғни, қазір ол 8 бит емес, 16. Яғни, 2 byte. Мәндерді дәл осылай есептеуге болады. 2^(16-1) = 2^15 = 32768. Бұл -32768-ден 32767-ге дейінгі диапазонды білдіреді. Ол кез келген ерекше жағдайларда өте сирек қолданылады. Java тілінің құжаттамасында айтылғандай: « үлкен массивтерде жадты сақтау үшін қысқа пайдалануға болады ».

int

Сонымен біз ең жиі қолданылатын түрге келдік. Ол 32 бит немесе 4 byte алады. Жалпы, біз еселеуді жалғастырамыз. Мәндер ауқымы -2^31-ден 2^31-1-ге дейін.

Максималды int мәні

int 2147483648 максималды мәні 1, бұл мүлде аз емес. Жоғарыда айтылғандай, есептеулерді оңтайландыру үшін, өйткені Қазіргі компьютерлер үшін олардың разрядтық сыйымдылығын ескере отырып санау ыңғайлырақ, мәліметтерді жасырын түрде int түрлендіруге болады. Міне, қарапайым мысал:
byte a = 1;
byte b = 2;
byte result = a + b;
Мұндай зиянсыз code, бірақ біз қатені аламыз: «қате: үйлеспейтін түрлер: int-тен byteқа жоғалту ықтимал түрлендіру». Сіз оны byte нәтижесіне түзетуіңіз керек = (byte)(a + b); Және тағы бір зиянсыз мысал. Келесі codeты іске қоссақ не болады?
int value = 4;
System.out.println(8/value);
System.out.println(9/value);
System.out.println(10/value);
System.out.println(11/value);
Ал біз қорытынды шығарамыз
2
2
2
2
* дүрбелең дыбыстары*
Мәселе мынада, int мәндерімен жұмыс істегенде, қалғаны толығымен жойылып, тек бүкіл бөлігін қалдырады (мұндай жағдайларда double қолданған дұрыс).

ұзақ

Біз екі еселеуді жалғастырамыз. Біз 32-ні 2-ге көбейтеміз және 64 бит аламыз. Дәстүр бойынша бұл 4 * 2, яғни 8 byte. Мәндер ауқымы -2^63-тен 2^63-ке дейін – 1. Артық. Бұл түрі үлкен, үлкен сандарды санауға мүмкіндік береді. Уақытпен жұмыс істегенде жиі қолданылады. Немесе, мысалы, ұзақ қашықтықта. Санның ұзын екенін көрсету үшін саннан кейін L – Long әріпін қойыңыз. Мысалы:
long longValue = 4;
longValue = 1l; // Не ошибка, но плохо читается
longValue = 2L; // Идеально
Мен өзімнен озғым келеді. Әрі қарай, примитивтермен an object ретінде жұмыс істеуге мүмкіндік беретін примитивтер үшін сәйкес орауыштардың бар екенін қарастырамыз. Бірақ қызықты ерекшелігі бар. Міне мысал: Бірдей Tutorialspoint онлайн компиляторын пайдалану арқылы келесі codeты тексеруге болады:
public class HelloWorld {

     public static void main(String []args) {
        printLong(4);
     }

    public static void printLong(long longValue) {
        System.out.println(longValue);
    }
}
Бұл code қатесіз жұмыс істейді, бәрі жақсы. Бірақ printLong әдісіндегі түр ұзыннан Longға ауыстырылғаннан кейін (яғни тип қарабайыр емес, нысанға айналады), Java үшін қандай параметрді өткізіп жатқанымыз түсініксіз болады. Ол int жіберіліп жатыр және қате болады деп есептей бастайды. Сондықтан, әдіс жағдайында 4L-ді нақты көрсету қажет болады. Деректер базасымен жұмыс істегенде идентификатор ретінде long жиі пайдаланылады.

Java float және Java double

Бұл түрлер қалқымалы нүкте типтері деп аталады. Яғни, бұл бүтін типтер емес. Қалқымалы тип 32 бит (int сияқты), ал double қос дәлдік типі деп аталады, сондықтан ол 64 бит (2-ге көбейту, бізге ұнайтындай). Мысалы:
public static void main(String []args){
        // float floatValue = 2.3; lossy conversion from double to float
        float floatValue = 2.3F;
        floatValue = 2.3f;
        double doubleValue = 2.3;
        System.out.println(floatValue);
        double cinema = 7D;
}
Міне, мәндер айырмашылығының мысалы (түрдің дәлдігіне байланысты):
public static void main(String []args){
        float piValue = (float)Math.PI;
        double piValueExt = Math.PI;
        System.out.println("Float value: " + piValue );
        System.out.println("Double value: " + piValueExt );
 }
Бұл қарабайыр типтер, мысалы, математикада қолданылады. Міне, дәлел, PI санын есептеу үшін тұрақты . Жалпы, сіз Math класының API интерфейсін көре аласыз. Тағы не маңызды және қызықты болуы керек: тіпті құжаттамада былай делінген: « Бұл деректер түрі ешқашан валюта сияқты нақты мәндер үшін пайдаланылмауы керек. Ол үшін оның орнына java.math.BigDecimal сыныбын пайдалану қажет. Сандар мен жолдар BigDecimal және Java платформасы ұсынған басқа пайдалы сыныптарды қамтиды. " Яғни, float және double түріндегі ақшаны есептеу қажет емес. NASA-дағы жұмыс мысалын пайдаланудағы дәлдік туралы мысал: Java BigDecimal, Жоғары дәлдіктегі есептеулермен жұмыс істеу . Оны өзіңіз сезіну үшін:
public static void main(String []args){
        float amount = 1.0000005F;
        float avalue = 0.0000004F;
        float result = amount - avalue;
        System.out.println(result);
}
Осы мысалды орындаңыз, содан кейін 5 және 4 сандарының алдына 0 қосыңыз. Ал сіз барлық сұмдықты көресіз) Орыс тілінде float және double туралы қызықты репортаж бар: https://youtu.be/1RCn5ruN1fk Жұмыс мысалдары BigDecimal көмегімен мына жерден көруге болады: BigDecimal көмегімен цент жасау Айтпақшы, float және double тек саннан да көп нәрсені қайтара алады. Мысалы, төмендегі мысал Infinity мәнін қайтарады:
public static void main(String []args){
        double positive_infinity = 12.0 / 0;
        System.out.println(positive_infinity);
}
Және бұл NAN қайтарады:
public static void main(String []args){
        double positive_infinity = 12.0 / 0;
        double negative_infinity = -15.0 / 0;
        System.out.println(positive_infinity + negative_infinity);
}
Бұл шексіздік туралы түсінікті. NaN дегеніміз не? Бұл сан емес , яғни нәтижені есептеу мүмкін емес және сан емес. Міне, мысал: -4-тің квадрат түбірін есептегіміз келеді. 4-тің квадрат түбірі 2. Яғни, 2-ні квадраттау керек, содан кейін 4-ті аламыз. -4 алу үшін нені квадраттау керек? Бұл жұмыс істемейді, өйткені... егер оң сан болса, онда ол қалады. Ал егер ол теріс болса, минус минус плюс береді. Яғни, ол есептелмейді.
public static void main(String []args){
        double sqrt = Math.sqrt(-4);
        System.out.println(sqrt + 1);
        if (Double.isNaN(sqrt)) {
           System.out.println("So sad");
        }
        System.out.println(Double.NaN == sqrt);
}
Міне, өзгермелі нүктелі сандар тақырыбына тағы бір тамаша шолу: Сіздің ойыңыз қайда?
Тағы не оқу керек:

Java логикалық

Келесі түрі логикалық тип (логикалық тип). Ол тек ақиқат немесе жалған мәндерді қабылдай алады, олар кілт сөздер. while циклдері сияқты логикалық операцияларда және if, switch көмегімен тармақталуда қолданылады. Мұнда қандай қызықты нәрселерді біле аласыз? Мысалы, теориялық тұрғыдан бізге тек 1 бит ақпарат қажет, 0 немесе 1, яғни шын немесе жалған. Бірақ шын мәнінде, логикалық көбірек жадты алады және бұл нақты JVM енгізуіне байланысты болады. Әдетте бұл int бағасымен бірдей. Тағы бір нұсқа - BitSet пайдалану. Мұнда Java негіздері кітабының қысқаша сипаттамасы берілген: BitSet

Java таңбасы

Енді біз соңғы қарабайыр типке жеттік. Сонымен, char ішіндегі деректер 16 бит алады және таңбаны сипаттайды. Java таңба үшін Юниcode codeтауын пайдаланады. Таңбаны екі кестеге сәйкес орнатуға болады (оны мына жерден көруге болады ):
  • Юниcode таңбалар кестесі
  • ASCII таңбалар кестесі
Java тіліндегі қарабайыр типтер: олар соншалықты қарабайыр емес - 3
Студиядағы мысал:
public static void main(String[] args) {
    char symbol = '\u0066'; // Unicode
    symbol = 102; // ASCII
    System.out.println(symbol);
}
Айтпақшы, char мәні сан болғандықтан, сома сияқты математикалық операцияларды қолдайды. Кейде бұл күлкілі салдарға әкелуі мүмкін:
public class HelloWorld{

    public static void main(String []args){
        String costForPrint = "5$";
        System.out.println("Цена только для вас " +
        + costForPrint.charAt(0) + getCurrencyName(costForPrint.charAt(1)));
    }

    public static String getCurrencyName(char symbol) {
        if (symbol == '$') {
            return " долларов";
        } else {
            throw new UnsupportedOperationException("Not implemented yet");
        }
    }

}
Мен онлайн IDE-ді tutorialspoint сайтынан тексеруді ұсынамын . Конференциялардың бірінде бұл басқатырғышты көргенде, көңіл-күйімді көтерді. Мысал сізге де ұнайды деп үміттенемін) ЖАҢАРТЫЛДЫ: Бұл Joker 2017-де болды, есеп: " Java Puzzlers NG S03 - Бәріңіз қайдан келдіңіз?! "

Литералдар

Литерал - анық көрсетілген мән. Литералдар көмегімен әртүрлі санау жүйелеріндегі мәндерді көрсетуге болады:
  • Ондық жүйе: 10
  • Оналтылық: 0x1F4, 0x-тен басталады
  • Сегіздік жүйе: 010, нөлден басталады.
  • Екілік жүйе (Java7-ден бастап): 0b101, 0b-ден басталады
Мен сегіздік жүйеге көбірек тоқталар едім, өйткені бұл күлкілі:
int costInDollars = 08;
Бұл code жолы компиляцияланбайды:
error: integer number too large: 08
Бұл бос сөз сияқты. Енді екілік және сегіздік жүйелер туралы еске түсірейік. Екілік жүйеде екі жоқ, өйткені екі мән бар (0-ден бастап). Ал сегіздік жүйеде нөлден басталатын 8 мән бар. Яғни, 8 мәнінің өзі жоқ. Сондықтан бұл бір қарағанда абсурд болып көрінетін қате. Есте сақтау керек, міне, мәндерді аударуға арналған «іздестіру» ережесі:
Java тіліндегі қарабайыр типтер: Олар соншалықты қарабайыр емес - 4

Қаптама кластары

Java тіліндегі примитивтердің өз орауыш сыныптары бар, сондықтан олармен нысан ретінде жұмыс істей аласыз. Яғни, әрбір қарабайыр тип үшін сәйкес сілтеме түрі бар. Java тіліндегі қарабайыр типтер: олар соншалықты қарабайыр емес - 5Орауыш сыныптары өзгермейді: бұл нысан жасалғаннан кейін оның күйін — мән өрісінің мәнін — өзгертуге болмайтынын білдіреді. Орауыш сыныптары соңғы ретінде жарияланады: нысандар, былайша айтқанда, тек оқуға арналған. Сондай-ақ, бұл сыныптардан мұрагер болу мүмкін еместігін атап өткім келеді. Java автоматты түрде қарабайыр түрлер мен олардың орауыштары арасында түрлендірулерді жасайды:
Integer x = 9;          // autoboxing
int n = new Integer(3); // unboxing
Қарапайым типтерді анықтамалық типтерге (int->Integer) түрлендіру процесі autoboxing деп аталады , ал кері процесс unboxing деп аталады . Бұл сыныптар an objectінің ішіндегі қарабайырды сақтауға мүмкіндік береді және нысанның өзі Объект сияқты әрекет етеді (жақсы, кез келген басқа нысан сияқты). Осының барлығы арқылы біз санды салыстыру, таңбаны регистрге түрлендіру, таңбаның әріп немесе сан екенін анықтау, ең аз санды іздеу және т.б. сияқты көптеген әртүрлі пайдалы статикалық әдістерді аламыз. Берілген функциялар жинағы тек қаптаманың өзіне байланысты. Int үшін орауыштың өзіңіздің іске асыру мысалы:
public class CustomerInt {

   private final int value;

   public CustomerInt(int value) {
       this.value = value;
   }

   public int getValue() {
       return value;
   }
}
Java.lang негізгі пакетінде Boolean, Byte, Short, Character, Integer, Float, Long, Double сыныптарының іске асырылулары бар және бізге өзімізден ештеңе жасаудың қажеті жоқ, тек дайынды қайта пайдалану керек. бір. Мысалы, мұндай сыныптар бізге, айталық, Тізімді құру мүмкіндігін береді , себебі Тізімде қарабайыр емес нысандар ғана болуы керек. Қарапайым түрдегі мәнді түрлендіру үшін статикалық valueOf әдістері бар, мысалы, Integer.valueOf(4) Integer түріндегі нысанды қайтарады. Кері түрлендіру үшін intValue(), longValue() және т.б. әдістері бар. Компилятор valueOf және *Value шақыруларын өздігінен кірістіреді, бұл автобокс пен автобокстың мәні. Жоғарыда келтірілген автобуып-түю және автоматты түрде ашу мысалы қалай көрінеді:
Integer x = Integer.valueOf(9);
int n = new Integer(3).intValue();
Автоматты буып-түю және автоматты түрде орауды осы мақаладан оқуға болады .

Cast

При работе с примитивами существует такое понятие How приведение типов, одно из не очень приятных свойств C++, тем не менее приведение типов сохранено и в языке Java. Иногда мы сталкиваемся с такими ситуациями, когда нам нужно совершать взаимодействия с данными разных типов. И очень хорошо, что в некоторых ситуациях это возможно. В случае с ссылочными переменными, там свои особенности, связанные с полиморфизмом и наследованием, но сегодня мы рассматриваем простые типы и соответственно приведение простых типов. Существует преобразование с расширением и преобразование сужающее. Всё на самом деле просто. Если тип данных становится больше (допустим, был int, а стал long), то тип становится шире (из 32 бит становится 64). И в этом случае мы не рискуем потерять данные, т.к. если влезло в int, то в long влезет тем более, поэтому данное приведение мы не замечаем, так How оно осуществляется автоматически. А вот в обратную сторону преобразование требует явного указания от нас, данное приведение типа называется — сужение. Так сказать, чтобы мы сами сказали: «Да, я даю себе отчёт в этом. В случае чего — виноват сам».
public static void main(String []args){
   int intValue = 128;
   byte value = (byte)intValue;
   System.out.println(value);
}
Whatбы потом в таком случае не говорor что «Ваша Джава плохая», когда получат внезапно -128 instead of 128 ) Мы ведь помним, что в byteе 127 верхнее meaning и всё что находилось выше него соответственно можно потерять. Когда мы явно превратor наш int в byte, то произошло переполнение и meaning стало -128.

Область видимости

Это то место в codeе, где данная переменная будет выполнять свои функции и хранить в себе Howое-то meaning. Когда же эта область закончится, переменная перестанет существовать и будет стерта из памяти и. How уже можно догадаться, посмотреть or получить ее meaning будет невозможно! Так что же это такое — область видимости? Java тіліндегі қарабайыр типтер: Олар соншалықты қарабайыр емес - 6Область определяется "блоком" — вообще всякой областью, замкнутой в фигурные скобки, выход за которые сулит удаление данных объявленных в ней. Или How минимум — сокрытие их от других блоков, открытых вне текущего. В Java область видимости определяется двумя основными способами:
  • Классом.
  • Методом.
Как я и сказал, переменная не видна codeу, если она определена за пределами блока, в котором она была инициализирована. Смотрим пример:
int x;
x = 6;
if (x >= 4) {
   int y = 3;
}
x = y;// переменная y здесь не видна!
И How итог мы получим ошибку:

Error:(10, 21) java: cannot find symbol
  symbol:   variable y
  location: class com.javaRush.test.type.Main
Области видимости могут быть вложенными (если мы объявor переменную в первом, внешнем блоке, то во внутреннем она будет видна).

Заключение

Сегодня мы познакомorсь с восемью примитивными типами в Java. Эти типы можно разделить на четыре группы:
  • Целые числа: byte, short, int, long — представляют собой целые числа со знаком.
  • Числа с плавающей точкой — эта группа включает себе float и double — типы, которые хранят числа с точностью до определённого знака после запятой.
  • Булевы значения — boolean — хранят значения типа "истина/ложь".
  • Таңбалар – бұл топқа таңба типі кіреді.
Жоғарыдағы мәтін көрсеткендей, Java тіліндегі примитивтер соншалықты қарапайым емес және көптеген мәселелерді тиімді шешуге мүмкіндік береді. Бірақ бұл біздің бағдарламамызда күтпеген мінез-құлыққа тап болғымыз келмесе, есте ұстауымыз керек кейбір мүмкіндіктерді де ұсынады. Олар айтқандай, бәрін төлеу керек. Егер біз «тік» (кең) диапазоны бар примитивті алғымыз келсе - ұзақ сияқты - біз жадтың үлкен бөлігін және қарама-қарсы бағытты бөлуді құрбан етеміз. Жадты сақтау және byteтарды пайдалану арқылы біз -128-ден 127-ге дейінгі шектеулі ауқымды аламыз.
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION