Szukaj…


Wprowadzenie

8 pierwotnych typów danych byte , short , int , long , char , boolean , float i double to typy, które przechowują najbardziej surowe dane liczbowe w programach Java.

Składnia

  • int aInt = 8; // Część definiująca (liczbowa) tej deklaracji int nazywana jest literałem.

  • int hexInt = 0x1a; // = 26; Możesz zdefiniować literały z wartościami szesnastkowymi poprzedzonymi 0x .

  • int binInt = 0b11010; // = 26; Możesz także zdefiniować literały binarne; z prefiksem 0b .

  • długi goodLong = 10000000000L; // Domyślnie literały całkowite są typu int. Dodając literę L na końcu literału, informujesz kompilator, że literał jest długi. Bez tego kompilator wygenerowałby błąd „Zbyt duża liczba całkowita”.

  • double aDouble = 3,14; // Literały zmiennoprzecinkowe są domyślnie typu double.

  • float aFloat = 3.14F; // Domyślnie ten literał byłby podwójny (i spowodowałby błąd „Niezgodne typy”), ale dodając F mówimy kompilatorowi, że jest zmiennoprzecinkowy.

Uwagi

Java ma 8 pierwotnych typów danych , a mianowicie boolean , byte , short , char , int , long , float i double . (Wszystkie pozostałe typy są typami referencyjnymi . Obejmuje to wszystkie typy tablic oraz wbudowane typy obiektów / klasy, które mają szczególne znaczenie w języku Java; np. String , Class and Throwable i jego podklasy.)

W wyniku wszystkich operacji (dodawanie, odejmowanie, mnożenie, etc.) na pierwotnym typu jest przynajmniej int , co dodanie short do short wytwarza int , podobnie jak dodanie byte do byte , lub char do char . Jeśli chcesz przypisać wynik z powrotem do wartości tego samego typu, musisz go rzutować. na przykład

byte a = 1;
byte b = 2;
byte c = (byte) (a + b);

Brak rzutowania spowoduje błąd kompilacji.

Wynika to z następującej części specyfikacji języka Java, §2.11.1 :

Kompilator koduje mnóstwo literalnych wartości typów byte i short za pomocą instrukcji wirtualnej maszyny Java, które rozszerzają te wartości na wartości typu int w czasie kompilacji lub w czasie wykonywania. Mnóstwo wartości literałów typu boolean i char są kodowane za pomocą instrukcji, które zerują literał do wartości typu int w czasie kompilacji lub w czasie wykonywania. [..]. Dlatego większość operacji na wartościach rzeczywistych typów typu boolean , byte , char i short są poprawnie wykonywane przez instrukcje działające na wartościach typu obliczeniowego int .

Powód tego jest również określony w tej sekcji:

Biorąc pod uwagę jednobajtowy rozmiar kodu operacyjnego maszyny wirtualnej Java, kodowanie typów w opcodes wywiera presję na projekt zestawu instrukcji. Jeśli każda wpisana instrukcja obsługiwałaby wszystkie typy danych w czasie wykonywania wirtualnej maszyny Java, byłoby więcej instrukcji niż można by przedstawić w byte . [...] W razie potrzeby można użyć osobnych instrukcji do konwersji między nieobsługiwanymi i obsługiwanymi typami danych.

Int pierwotny

Prymitywny typ danych, taki jak int przechowuje wartości bezpośrednio do zmiennej, która go używa, tymczasem zmienna zadeklarowana za pomocą Integer przechowuje odwołanie do wartości.

Według java API : „Klasa Integer otacza wartość pierwotnego typu int obiektem. Obiekt typu Integer zawiera pojedyncze pole, którego typem jest int.”

Domyślnie int jest 32-bitową liczbą całkowitą ze znakiem. Może przechowywać minimalną wartość -2 31 i maksymalną wartość 2 31-1 .

int example = -42;
int myInt = 284;
int anotherInt = 73;

int addedInts = myInt + anotherInt; // 284 + 73 = 357
int subtractedInts = myInt - anotherInt; // 284 - 73 = 211

Jeśli chcesz zapisać liczbę spoza tego zakresu, zamiast tego należy użyć wartości long . Przekroczenie zakresu wartości int prowadzi do przepełnienia liczby całkowitej, powodując dodanie wartości przekraczającej zakres do przeciwnego miejsca zakresu (dodatnia staje się ujemna i odwrotnie). Wartość wynosi ((value - MIN_VALUE) % RANGE) + MIN_VALUE lub ((value + 2147483648) % 4294967296) - 2147483648

int demo = 2147483647; //maximum positive integer
System.out.println(demo); //prints 2147483647
demo = demo + 1; //leads to an integer overflow
System.out.println(demo); // prints -2147483648

Maksymalne i minimalne wartości int można znaleźć na:

int high = Integer.MAX_VALUE;    // high == 2147483647
int low = Integer.MIN_VALUE;     // low == -2147483648

Domyślna wartość int to 0

int defaultInt;    // defaultInt == 0

Krótki prymityw

short to 16-bitowa liczba całkowita ze znakiem. Ma minimalną wartość -2 15 (-32 768) i maksymalną wartość 2 15 ‑1 (32 767)

short example = -48;
short myShort = 987;
short anotherShort = 17;

short addedShorts = (short) (myShort + anotherShort); // 1,004
short subtractedShorts = (short) (myShort - anotherShort); // 970

Maksymalne i minimalne wartości short można znaleźć na:

short high = Short.MAX_VALUE;        // high == 32767
short low = Short.MIN_VALUE;         // low == -32768

Domyślna wartość short to 0

short defaultShort;    // defaultShort == 0

Długi prymityw

Domyślnie long jest 64-bitową liczbą całkowitą ze znakiem (w Javie 8 może być podpisany lub niepodpisany). Podpisany, może przechowywać minimalną wartość -2 63 , a maksymalną wartość 2 63-1 , a bez znaku może przechowywać minimalną wartość 0 i maksymalną wartość 2 64-1

long example = -42;
long myLong = 284;
long anotherLong = 73;

//an "L" must be appended to the end of the number, because by default,
//numbers are assumed to be the int type. Appending an "L" makes it a long
//as 549755813888 (2 ^ 39) is larger than the maximum value of an int (2^31 - 1),
//"L" must be appended 
long bigNumber = 549755813888L;

long addedLongs = myLong + anotherLong; // 284 + 73 = 357
long subtractedLongs = myLong - anotherLong; // 284 - 73 = 211

Maksymalne i minimalne wartości long można znaleźć na:

long high = Long.MAX_VALUE;    // high == 9223372036854775807L
long low = Long.MIN_VALUE;     // low == -9223372036854775808L

Domyślną wartością long jest 0L

long defaultLong;    // defaultLong == 0L

Uwaga: litera „L” dołączona na końcu long literału nie uwzględnia wielkości liter, jednak dobrą praktyką jest stosowanie kapitału, ponieważ łatwiej jest odróżnić go od cyfry:

2L == 2l;            // true

Ostrzeżenie: Java buforuje instancje obiektów liczb całkowitych z zakresu od -128 do 127. Rozumowanie wyjaśniono tutaj: https://blogs.oracle.com/darcy/entry/boxing_and_caches_integer_valueof

Można znaleźć następujące wyniki:

Long val1 = 127L;
Long val2 = 127L;

System.out.println(val1 == val2); // true

Long val3 = 128L;
Long val4 = 128L;

System.out.println(val3 == val4); // false

Aby poprawnie porównać 2 wartości Długości obiektu, użyj następującego kodu (od Java 1.7 i nowszych):

Long val3 = 128L;
Long val4 = 128L;

System.out.println(Objects.equal(val3, val4)); // true

Porównanie długiej prymitywnej z długością obiektu nie da fałszywego negatywu, jak w przypadku porównania 2 obiektów z ==.

Prymityw boolowski

boolean może przechowywać jedną z dwóch wartości, true lub false

boolean foo = true;
System.out.println("foo = " + foo);                // foo = true

boolean bar = false;
System.out.println("bar = " + bar);                // bar = false

boolean notFoo = !foo;
System.out.println("notFoo = " + notFoo);          // notFoo = false

boolean fooAndBar = foo && bar;
System.out.println("fooAndBar = " + fooAndBar);    // fooAndBar = false

boolean fooOrBar = foo || bar;
System.out.println("fooOrBar = " + fooOrBar);      // fooOrBar = true

boolean fooXorBar = foo ^ bar;
System.out.println("fooXorBar = " + fooXorBar);    // fooXorBar = true

Domyślna wartość boolean to false

boolean defaultBoolean;    // defaultBoolean == false

Prymityw bajtów

byte to 8-bitowa liczba całkowita ze znakiem. Może przechowywać minimalną wartość -2 7 (-128) i maksymalną wartość 2 7-1 (127)

byte example = -36;
byte myByte = 96;
byte anotherByte = 7;

byte addedBytes = (byte) (myByte + anotherByte); // 103
byte subtractedBytes = (byte) (myBytes - anotherByte); // 89

Maksymalne i minimalne wartości byte można znaleźć na:

byte high = Byte.MAX_VALUE;        // high == 127
byte low = Byte.MIN_VALUE;         // low == -128

Domyślna wartość byte to 0

byte defaultByte;    // defaultByte == 0

Prymityw pływaka

Liczba float to 32-bitowa liczba float z pojedynczą precyzją IEEE 754. Domyślnie dziesiętne są interpretowane jako liczby podwójne. Aby utworzyć liczbę float , po prostu dodaj f do literału dziesiętnego.

double doubleExample = 0.5;      // without 'f' after digits = double
float floatExample = 0.5f;       // with 'f' after digits    = float

float myFloat = 92.7f;           // this is a float...
float positiveFloat = 89.3f;     // it can be positive,
float negativeFloat = -89.3f;    // or negative
float integerFloat = 43.0f;      // it can be a whole number (not an int)
float underZeroFloat = 0.0549f;  // it can be a fractional value less than 0

Pływaki obsługują pięć typowych operacji arytmetycznych: dodawanie, odejmowanie, mnożenie, dzielenie i moduł.

Uwaga: Poniższe informacje mogą się nieznacznie różnić w wyniku błędów zmiennoprzecinkowych. Niektóre wyniki zostały zaokrąglone w celu zachowania przejrzystości i czytelności (tzn. Wydrukowany wynik z przykładu dodania wynosił w rzeczywistości 34.600002).

// addition
float result = 37.2f + -2.6f;  // result: 34.6

// subtraction
float result = 45.1f - 10.3f;    // result: 34.8

// multiplication
float result = 26.3f * 1.7f;   // result: 44.71

// division
float result = 37.1f / 4.8f;   // result: 7.729166

// modulus
float result = 37.1f % 4.8f;   // result: 3.4999971

Ze względu na sposób przechowywania liczb zmiennoprzecinkowych (tj. W postaci binarnej) wiele liczb nie ma dokładnej reprezentacji.

float notExact = 3.1415926f;
System.out.println(notExact); // 3.1415925

Podczas korzystania float jest w porządku dla większości zastosowań, ani float ani double powinien być używany do przechowywania dokładnych reprezentacji liczb dziesiętnych (np kwot pieniężnych) lub numery, gdzie wymagana jest większa precyzja. Zamiast tego należy użyć klasy BigDecimal .

Domyślna wartość liczb float to 0,0f .

float defaultFloat;    // defaultFloat == 0.0f

Liczba float jest dokładna do błędu około 1 na 10 milionów.

Uwaga: Float.POSITIVE_INFINITY , Float.NEGATIVE_INFINITY , Float.NaN są wartościami float . NaN oznacza wyniki operacji, których nie można ustalić, takich jak podzielenie 2 wartości nieskończonych. Ponadto 0f i -0f są różne, ale == daje true:

float f1 = 0f;
float f2 = -0f;
System.out.println(f1 == f2); // true
System.out.println(1f / f1); // Infinity
System.out.println(1f / f2); // -Infinity
System.out.println(Float.POSITIVE_INFINITY / Float.POSITIVE_INFINITY); // NaN

Podwójny prymityw

double to 64-bitowa liczba zmiennoprzecinkowa IEEE 754 o podwójnej precyzji.

double example = -7162.37;
double myDouble = 974.21;
double anotherDouble = 658.7;

double addedDoubles = myDouble + anotherDouble; // 315.51
double subtractedDoubles = myDouble - anotherDouble; // 1632.91

double scientificNotationDouble = 1.2e-3;    // 0.0012

Ze względu na sposób przechowywania liczb zmiennoprzecinkowych wiele liczb nie ma dokładnej reprezentacji.

double notExact = 1.32 - 0.42; // result should be 0.9
System.out.println(notExact); // 0.9000000000000001

Podczas gdy używanie double jest dobre dla większości aplikacji, nie należy używać liczb float ani double do przechowywania dokładnych liczb, takich jak waluta. Zamiast tego należy użyć klasy BigDecimal

Domyślna wartość double to 0.0d

public double defaultDouble;    // defaultDouble == 0.0

Uwaga: Double.POSITIVE_INFINITY , Double.NEGATIVE_INFINITY , Double.NaNdouble wartościami. NaN oznacza wyniki operacji, których nie można ustalić, takich jak podzielenie 2 wartości nieskończonych. Ponadto 0d i -0d są różne, ale == daje true:

double d1 = 0d;
double d2 = -0d;
System.out.println(d1 == d2); // true
System.out.println(1d / d1); // Infinity
System.out.println(1d / d2); // -Infinity
System.out.println(Double.POSITIVE_INFINITY / Double.POSITIVE_INFINITY); // NaN

Prymityw char

char może przechowywać jeden 16-bitowy znak Unicode. Dosłowny znak jest ujęty w pojedyncze cudzysłowy

char myChar = 'u';
char myChar2 = '5';
char myChar3 = 65; // myChar3 == 'A'

Ma minimalną wartość \u0000 (0 w postaci dziesiętnej, zwanej także znakiem pustym ) i maksymalną wartość \uffff (65 535).

Domyślna wartość char to \u0000 .

char defaultChar;    // defaultChar == \u0000

W celu zdefiniowania wartości znaku ' char ' użyć sekwencji specjalnej (znak poprzedzony odwrotnym ukośnikiem):

char singleQuote = '\'';

Istnieją również inne sekwencje specjalne:

char tab = '\t';
char backspace = '\b';
char newline = '\n';
char carriageReturn = '\r';
char formfeed = '\f';
char singleQuote = '\'';
char doubleQuote = '\"'; // escaping redundant here; '"' would be the same; however still allowed
char backslash = '\\';
char unicodeChar = '\uXXXX' // XXXX represents the Unicode-value of the character you want to display

Możesz zadeklarować char dowolnego znaku Unicode.

char heart = '\u2764';
System.out.println(Character.toString(heart)); // Prints a line containing "❤".

Możliwe jest również dodanie do char . np. aby iterować każdą małą literę, możesz wykonać następujące czynności:

for (int i = 0; i <= 26; i++) {
    char letter = (char) ('a' + i);
    System.out.println(letter);
}

Reprezentacja wartości ujemnej

Java i większość innych języków przechowują ujemne liczby całkowite w reprezentacji zwanej notacją dopełniacza 2 .

Dla unikalnej reprezentacji binarnej typu danych przy użyciu n bitów wartości są kodowane w następujący sposób:

Najmniej znaczące n-1 bity przechowują dodatnią liczbę całkowitą x w reprezentacji całkowej. Większość sklepów znacznej wartości nieco wartość vith s . Wartość powtarzana przez te bity to

x - s * 2 n-1

tzn. jeśli najbardziej znaczącym bitem jest 1, to wartość jest tylko o 1 większa niż liczba, którą możesz reprezentować za pomocą innych bitów ( 2 n-2 + 2 n-3 + ... + 2 1 + 2 0 = 2 n-1 - 1 ) jest odejmowane, umożliwiając unikalną reprezentację binarną dla każdej wartości od - 2 n-1 (s = 1; x = 0) do 2 n-1 - 1 (s = 0; x = 2 n-1 - 1).

Ma to również ładny efekt uboczny, polegający na tym, że można dodawać reprezentacje binarne tak, jakby były dodatnimi liczbami binarnymi:

v1 = x1 - s1 * 2n-1
v2 = x2 - s2 * 2n-1
s1 s2 Przepełnienie x1 + x2 wynik dodania
0 0 Nie x1 + x2 = v1 + v2
0 0 tak za duży, aby można go było przedstawić za pomocą typu danych (przepełnienie)
0 1 Nie
x1 + x2 - 2n-1 = x1 + x2 - s2 * 2n-1
= v1 + v2
0 1 tak
(x1 + x2) mod 2n-1 = x1 + x2 - 2n-1
= v1 + v2
1 0 * patrz wyżej (wymiany swapów)
1 1 Nie za mały, aby można go było przedstawić za pomocą typu danych (x1 + x2 - 2 n <-2 n-1 ; niedomiar)
1 1 tak
(x1 + x2) mod 2n-1 - 2n-1 = (x1 + x2 - 2n-1) - 2n-1
= (x1 - s1 * 2n-1) + (x2 - s2 * 2n-1)
= v1 + v2

Zauważ, że ten fakt ułatwia znalezienie binarnej reprezentacji odwrotności dodatku (tj. Wartości ujemnej):

Zauważ, że dodanie bitowego uzupełnienia do liczby powoduje, że wszystkie bity są 1. Teraz dodaj 1, aby przelać wartość i otrzymasz neutralny element 0 (wszystkie bity 0).

Tak więc wartość ujemną liczby i można obliczyć za pomocą (ignorując możliwą promocję do int tutaj)

(~i) + 1

Przykład: przyjmowanie wartości ujemnej 0 ( byte ):

Wynik zanegowania 0 wynosi 11111111 . Dodanie 1 daje wartość 100000000 (9 bitów). Ponieważ byte może przechowywać tylko 8 bitów, lewa wartość jest obcinana, a wynik to 00000000

Oryginalny Proces Wynik
0 (00000000) Negować -0 (11111111)
11111111 Dodaj 1 do pliku binarnego 100000000
100000000 Obetnij do 8 bitów 00000000 (-0 równa się 0)

Zużycie pamięci przez operacje podstawowe a operacje podstawowe w pudełkach

Prymitywny Rodzaj pudełka Rozmiar pamięci pierwotnej / zapakowanej
boolean Boolean 1 bajt / 16 bajtów
bajt Bajt 1 bajt / 16 bajtów
krótki Krótki 2 bajty / 16 bajtów
zwęglać Zwęglać 2 bajty / 16 bajtów
int Liczba całkowita 4 bajty / 16 bajtów
długo Długo 8 bajtów / 16 bajtów
pływak Pływak 4 bajty / 16 bajtów
podwójnie Podwójnie 8 bajtów / 16 bajtów

Obiekty w pudełkach zawsze wymagają 8 bajtów do zarządzania typami i pamięcią, a ponieważ rozmiar obiektów jest zawsze wielokrotnością 8, wszystkie typy w pudełkach wymagają łącznie 16 bajtów . Ponadto każde użycie obiektu w pudełku pociąga za sobą przechowywanie odwołania, które stanowi kolejne 4 lub 8 bajtów, w zależności od opcji JVM i JVM.

W operacjach intensywnie wykorzystujących dane zużycie pamięci może mieć duży wpływ na wydajność. Zużycie pamięci rośnie jeszcze bardziej przy użyciu tablic: tablica float[5] będzie wymagała tylko 32 bajtów; podczas gdy Float[5] przechowujący 5 różnych wartości innych niż null będzie wymagał łącznie 112 bajtów (w 64 bitach bez skompresowanych wskaźników, zwiększa się to do 152 bajtów).

Buforowane wartości pudełkowe

Narzuty przestrzenne typów pudełkowych można do pewnego stopnia ograniczyć dzięki pamięci podręcznej wartości pudełkowej. Niektóre typy pudełkowe implementują pamięć podręczną instancji. Na przykład domyślnie klasa Integer będzie buforować instancje w celu reprezentowania liczb z zakresu od -128 do +127 . Nie zmniejsza to jednak dodatkowych kosztów wynikających z pośredniej pamięci dodatkowej.

Jeśli utworzysz wystąpienie typu pudełkowego albo przez autoboxing, albo przez wywołanie metody static valueOf(primitive) , system wykonawczy spróbuje użyć wartości buforowanej. Jeśli aplikacja używa wielu wartości w zakresie buforowanym, może to znacznie zmniejszyć karę pamięci związaną z używaniem typów pudełkowych. Oczywiście, jeśli tworzysz instancje wartości w pudełku „ręcznie”, lepiej jest użyć valueOf niż new . ( new operacja zawsze tworzy nową instancję). Jeśli jednak większość twoich wartości nie znajduje się w zbuforowanym zakresie, szybsze może być wywołanie new i zapisanie wyszukiwania w pamięci podręcznej.

Konwertowanie prymitywów

W Javie możemy konwertować między wartościami całkowitymi a wartościami zmiennoprzecinkowymi. Ponadto, ponieważ każdy odpowiada postaci do liczby w kodowaniu Unicode char typy mogą być przekształcone do i od liczby całkowite i zmiennoprzecinkowych. boolean jest jedynym pierwotnym typem danych, którego nie można przekonwertować na ani z żadnego innego pierwotnego typu danych.

Istnieją dwa rodzaje konwersji: konwersja poszerzająca i konwersja zawężająca .

Konwersja rozszerzająca ma miejsce, gdy wartość jednego typu danych jest konwertowana na wartość innego typu danych, który zajmuje więcej bitów niż poprzedni. W tym przypadku nie ma problemu utraty danych.

Odpowiednio, zawężenie konwersji następuje, gdy wartość jednego typu danych jest konwertowana na wartość innego typu danych, który zajmuje mniej bitów niż poprzedni. W takim przypadku może wystąpić utrata danych.

Java automatycznie wykonuje konwersje rozszerzające . Ale jeśli chcesz wykonać zwężającą się konwersję (jeśli masz pewność, że nie nastąpi utrata danych), możesz zmusić Javę do wykonania konwersji za pomocą konstrukcji języka znanej jako cast .

Poszerzenie konwersji:

int a = 1;    
double d = a;    // valid conversion to double, no cast needed (widening)

Zawężenie konwersji:

double d = 18.96
int b = d;       // invalid conversion to int, will throw a compile-time error
int b = (int) d; // valid conversion to int, but result is truncated (gets rounded down)
                 // This is type-casting
                 // Now, b = 18

Cheatheet typów pierwotnych

Tabela przedstawiająca zakres wielkości i wartości wszystkich typów pierwotnych:

typ danych reprezentacja numeryczna Zakres wartości domyślna wartość
boolean nie dotyczy fałszywe i prawdziwe fałszywy
bajt 8-bitowy podpis -2 7 do 2 7-1 0
-128 do +127
krótki 16-bitowy podpisany -2 15 do 2 15-1 0
-32 768 do +32 767
int 32-bitowy podpisany -2 31 do 2 31-1 0
-2 147 483 648 do +14 147 483 647
długo 64-bitowy podpisany -2 63 do 2 63-1 0L
-9,223,372,036,854,775,808 do 9,223,372,036,854,775,807
pływak 32-bitowy zmiennoprzecinkowy 1.401298464e-45 do 3.402823466e + 38 (dodatnie lub ujemne) 0,0 F.
podwójnie 64-bitowy zmiennoprzecinkowy 4,94065645841246544e-324d do 1.79769313486231570e + 308d (dodatnie lub ujemne) 0,0D
zwęglać 16-bit bez znaku 0–2 16–1 0
Od 0 do 65 535

Uwagi:

  1. Specyfikacja języka Java nakazuje, aby podpisywać typy całkowite ( byte do long ) używają binarnej reprezentacji dwójkowej dopełniacza, a typy zmiennoprzecinkowe używają standardowych reprezentacji binarnych zmiennoprzecinkowych IEE 754.
  2. Java 8 i nowsze wersje zapewniają metody wykonywania niepodpisanych operacji arytmetycznych na int i long . Chociaż metody te pozwalają programowi traktować wartości odpowiednich typów jako niepodpisane, typy pozostają typami podpisanymi.
  3. Najmniejszy zmiennoprzecinkowy pokazany powyżej jest nienormalny ; tzn. mają mniejszą dokładność niż normalna wartość. Najmniejsze liczby normalne to 1,175494351e-38 i 2,2250738585072014e-308
  4. char zwykle oznacza Unicode / UTF-16 jednostki kodu.
  5. Chociaż wartość boolean zawiera tylko jeden bit informacji, jej rozmiar w pamięci różni się w zależności od implementacji wirtualnej maszyny Java (patrz typ logiczny ).


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow