Zoeken…


Invoering

De 8 primitieve gegevenstypes byte , short , int , long , char , boolean , float en double zijn de typen die de meeste ruwe numerieke gegevens opslaan in Java-programma's.

Syntaxis

  • int aInt = 8; // Het definiërende (nummer) deel van deze int-declaratie wordt letterlijk genoemd.

  • int hexInt = 0x1a; // = 26; U kunt literalen definiëren met hex-waarden voorafgegaan door 0x .

  • int binInt = 0b11010; // = 26; U kunt ook binaire literalen definiëren; voorafgegaan door 0b .

  • lang goodLong = 10000000000L; // Standaard zijn literaire getallen van het type int. Door de L aan het einde van het letterlijke toe te voegen, vertel je de compiler dat het letterlijke lang is. Zonder dit zou de compiler de fout 'Geheel getal te groot' geven.

  • double aDouble = 3.14; // Literatuur met drijvende komma is standaard dubbel.

  • float aFloat = 3.14F; // Standaard zou dit letterlijke dubbel zijn geweest (en een fout "Incompatibele typen" hebben veroorzaakt), maar door een F toe te voegen vertellen we de compiler dat het een float is.

Opmerkingen

Java heeft 8 primitieve gegevenstypen , namelijk boolean , byte , short , char , int , long , float en double . (Alle andere typen zijn referentietypen . Dit omvat alle arraytypen en ingebouwde objecttypen / klassen die een speciale betekenis hebben in de Java-taal; bijvoorbeeld String , Class en Throwable en de bijbehorende subklassen.)

Het resultaat van alle bewerkingen (optellen, aftrekken, vermenigvuldigen, enz.) Op een primitief type is ten minste een int , dus het toevoegen van een short aan een short produceert een int , net als het toevoegen van een byte aan een byte , of een char aan een char . Als u het resultaat daarvan terug wilt toewijzen aan een waarde van hetzelfde type, moet u het casten. bv

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

Het niet casten van de bewerking resulteert in een compileerfout.

Dit komt door het volgende deel van de Java Language Spec, §2.11.1 :

Een compiler codeert ladingen van letterlijke waarden van het type byte en short met behulp van Java Virtual Machine-instructies die deze waarden tijdens de compilatie of runtime naar waarden van het type int uitbreiden. Tal van letterlijke waarden van de typen boolean en char worden gecodeerd met behulp van instructies die de letterlijke waarde nul uitbreiden tot een waarde van het type int tijdens het compileren of uitvoeren. [..]. De meeste bewerkingen op waarden van werkelijke typen boolean , byte , char en short worden dus correct uitgevoerd door instructies die werken op waarden van het computationele type int .

De reden hierachter staat ook in die sectie:

Gezien de one-byte opcodegrootte van de Java Virtual Machine, zetten coderingstypen in opcodes druk op het ontwerp van de instructieset. Als elke getypte instructie alle runtime-gegevenstypen van de Java Virtual Machine zou ondersteunen, zouden er meer instructies zijn dan in een byte zou kunnen worden weergegeven. [...] Afzonderlijke instructies kunnen worden gebruikt om indien nodig tussen niet-ondersteunde en ondersteunde gegevenstypen te converteren.

De int primitieve

Een primitief gegevenstype zoals int bevat waarden rechtstreeks in de variabele die het gebruikt, terwijl een variabele die is gedeclareerd met Integer een verwijzing naar de waarde bevat.

Volgens Java API : "De klasse Integer wikkelt een waarde van het primitieve type int in een object. Een object van het type Integer bevat een enkel veld waarvan het type int is."

Standaard is int een 32-bits geheel getal met teken. Het kan een minimumwaarde van -2 31 opslaan, en een maximumwaarde van 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

Als u een nummer buiten dit bereik wilt opslaan, moet u in plaats daarvan long gebruiken. Overschrijding van het waardebereik van int leidt tot een integeroverloop, waardoor de waarde die het bereik overschrijdt wordt toegevoegd aan de tegenovergestelde locatie van het bereik (positief wordt negatief en vice versa). De waarde is ((value - MIN_VALUE) % RANGE) + MIN_VALUE , of ((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

De maximale en minimale waarden van int zijn te vinden op:

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

De standaardwaarde van een int is 0

int defaultInt;    // defaultInt == 0

De korte primitief

Een short is een 16-bits geheel getal met teken. Het heeft een minimale waarde van -2 15 (-32.768) en een maximale waarde van 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

De maximale en minimale waarden van short zijn te vinden op:

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

De standaardwaarde van een short is 0

short defaultShort;    // defaultShort == 0

De lange primitieve

Standaard is long een 64-bits ondertekend geheel getal (in Java 8 kan het ondertekend of niet-ondertekend zijn). Ondertekend kan het een minimale waarde opslaan van -2 63 en een maximale waarde van 2 63 - 1, en niet ondertekend kan het een minimale waarde opslaan van 0 en een maximale waarde van 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

De maximale en minimale waarden van long zijn te vinden op:

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

De standaardwaarde van een long is 0L

long defaultLong;    // defaultLong == 0L

Opmerking: de letter "L" die aan het einde van een long letter is toegevoegd, is niet hoofdlettergevoelig, maar het is een goede gewoonte om kapitaal te gebruiken, omdat het gemakkelijker te onderscheiden is van cijfer één:

2L == 2l;            // true

Waarschuwing: Java slaat Integer objecten op in het bereik van -128 tot 127. De redenering wordt hier uitgelegd: https://blogs.oracle.com/darcy/entry/boxing_and_caches_integer_valueof

De volgende resultaten zijn te vinden:

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

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

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

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

Gebruik de volgende code (vanaf Java 1.7) om 2 object lange waarden goed te vergelijken:

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

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

Het vergelijken van een primitieve long met een object long zal niet resulteren in een vals negatief zoals 2 objecten vergelijken met == doet.

De Booleaanse primitief

Een boolean kan een van twee waarden opslaan, true of niet 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

De standaardwaarde van een boolean is false

boolean defaultBoolean;    // defaultBoolean == false

De byte primitief

Een byte is een 8-bits geheel getal met teken. Het kan een minimumwaarde van -2 7 (-128) en een maximumwaarde van 2 7 - 1 (127) opslaan

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

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

De maximale en minimale waarden van byte zijn te vinden op:

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

De standaardwaarde van een byte is 0

byte defaultByte;    // defaultByte == 0

De float primitief

Een float is een 32-bits IEEE 754-drijvende-kommagetal met enkele precisie. Decimalen worden standaard als dubbele waarden geïnterpreteerd. Voeg eenvoudig een f aan de decimale letter om een float te maken.

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

Floats verwerken de vijf gebruikelijke rekenkundige bewerkingen: optellen, aftrekken, vermenigvuldigen, delen en modulus.

Opmerking: het volgende kan enigszins variëren als gevolg van drijvende kommafouten. Sommige resultaten zijn afgerond ter wille van de duidelijkheid en leesbaarheid (dwz het afgedrukte resultaat van het toevoegingsvoorbeeld was eigenlijk 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

Vanwege de manier waarop floating point-nummers worden opgeslagen (dwz in binaire vorm), hebben veel nummers geen exacte weergave.

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

Hoewel het gebruik van float prima is voor de meeste toepassingen, moet float of double niet worden gebruikt om exacte representaties van decimale getallen (zoals geldbedragen) op te slaan, of getallen waarvoor een hogere precisie vereist is. In plaats daarvan moet de klasse BigDecimal worden gebruikt.

De standaardwaarde van een float is 0.0f .

float defaultFloat;    // defaultFloat == 0.0f

Een float is precies tot ongeveer een fout van 1 op 10 miljoen.

Opmerking: Float.POSITIVE_INFINITY , Float.NEGATIVE_INFINITY , Float.NaN zijn float waarden. NaN staat voor resultaten van bewerkingen die niet kunnen worden bepaald, zoals het delen van 2 oneindige waarden. Verder zijn 0f en -0f verschillend, maar == levert waar op:

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

De dubbele primitief

Een double is een 64-bit IEEE 754 drijvende-kommagetal met dubbele precisie.

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

Vanwege de manier waarop floating point-nummers worden opgeslagen, hebben veel nummers geen exacte weergave.

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

Hoewel double gebruik prima is voor de meeste toepassingen, moet noch float noch double worden gebruikt om precieze getallen zoals valuta op te slaan. In plaats daarvan moet de klasse BigDecimal worden gebruikt

De standaardwaarde van een double waarde is 0.0d

public double defaultDouble;    // defaultDouble == 0.0

Opmerking: Double.POSITIVE_INFINITY , Double.NEGATIVE_INFINITY , Double.NaN zijn double waarden. NaN staat voor resultaten van bewerkingen die niet kunnen worden bepaald, zoals het delen van 2 oneindige waarden. Verder zijn 0d en -0d verschillend, maar == levert waar op:

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

De char primitieve

Een char kan een enkel 16-bit Unicode-teken opslaan. Een letterlijke letter staat tussen enkele aanhalingstekens

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

Het heeft een minimale waarde van \u0000 (0 in de decimale weergave, ook wel het null-teken genoemd ) en een maximale waarde van \uffff (65.535).

De standaardwaarde van een char is \u0000 .

char defaultChar;    // defaultChar == \u0000

Teneinde een residu van definiëren ' waarde een escape (leesteken voorafgegaan door een backslash) moet worden gebruikt:

char singleQuote = '\'';

Er zijn ook andere escape-reeksen:

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

U kunt een char van elk Unicode-teken declareren.

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

Het is ook mogelijk om toe te voegen aan een char . om bijvoorbeeld elke kleine letter te doorlopen, kunt u het volgende doen:

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

Weergave van negatieve waarden

Java en de meeste andere talen slaan negatieve integrale getallen op in een representatie die de complementnotatie van 2 wordt genoemd .

Voor een unieke binaire weergave van een gegevenstype met n bits, worden waarden als volgt gecodeerd:

De minst significante n-1 bits slaan een positief integraal getal x in integraalweergave. De meest significante waarde slaat een bit met waarde s . De waarde die wordt weergegeven door die bits is

x - s * 2 n-1

dwz als de meest significante bit 1 is, dan is een waarde die net 1 groter is dan het aantal dat u zou kunnen vertegenwoordigen met de andere bits ( 2 n-2 + 2 n-3 + ... + 2 1 + 2 0 = 2 n-1 - 1 ) wordt afgetrokken waardoor een unieke binaire weergave voor elke waarde van - 2 n-1 (s = 1; x = 0) tot 2 n-1 - 1 (s = 0; x = 2 n-1 - 1).

Dit heeft ook het leuke neveneffect, dat je de binaire representaties kunt toevoegen alsof het positieve binaire getallen waren:

v1 = x1 - s1 * 2n-1
v2 = x2 - s2 * 2n-1
s1 s2 x1 + x2 overloop toevoeging resultaat
0 0 Nee x1 + x2 = v1 + v2
0 0 Ja te groot om te worden weergegeven met gegevenstype (overloop)
0 1 Nee
x1 + x2 - 2n-1 = x1 + x2 - s2 * 2n-1
= v1 + v2
0 1 Ja
(x1 + x2) mod 2n-1 = x1 + x2 - 2n-1
= v1 + v2
1 0 * zie hierboven (wissel van plaats)
1 1 Nee te klein om te worden weergegeven met gegevenstype (x1 + x2 - 2 n <-2 n-1 ; underflow)
1 1 Ja
(x1 + x2) mod 2n-1 - 2n-1 = (x1 + x2 - 2n-1) - 2n-1
= (x1 - s1 * 2n-1) + (x2 - s2 * 2n-1)
= v1 + v2

Merk op dat dit feit het vinden van binaire representatie van het additief omgekeerd (dwz de negatieve waarde) gemakkelijk maakt:

Merk op dat het toevoegen van de bitsgewijze aanvulling aan het getal erin resulteert dat alle bits 1 zijn. Voeg nu 1 toe om de waarde te laten overstromen en je krijgt het neutrale element 0 (alle bits 0).

Dus de negatieve waarde van een getal dat i kan berekenen met (negeren van mogelijke promotie naar int hier)

(~i) + 1

Voorbeeld: de negatieve waarde van 0 ( byte ) nemen:

Het resultaat van het negeren van 0 is 11111111 . Het toevoegen van 1 geeft een waarde van 100000000 (9 bits). Omdat een byte slechts 8 bits kan opslaan, wordt de meest linkse waarde afgekapt en is het resultaat 00000000

origineel Werkwijze Resultaat
0 (00000000) Negatief -0 (11111111)
11111111 Voeg 1 toe aan binary 100000000
100000000 Afkorten tot 8 bits 00000000 (-0 is gelijk aan 0)

Geheugenverbruik van primitieven versus in dozen verpakte primitieven

Primitief Boxed Type Geheugengrootte van primitief / in een doos
boolean Boolean 1 byte / 16 bytes
byte Byte 1 byte / 16 bytes
kort kort 2 bytes / 16 bytes
verkolen verkolen 2 bytes / 16 bytes
int Geheel getal 4 bytes / 16 bytes
lang Lang 8 bytes / 16 bytes
vlotter Vlotter 4 bytes / 16 bytes
dubbele Dubbele 8 bytes / 16 bytes

Boxed objecten vereisen altijd 8 bytes voor type- en geheugenbeheer, en omdat de grootte van objecten altijd een veelvoud van 8 is, vereisen boxed types allemaal 16 bytes in totaal . Bovendien betekent elk gebruik van een object in een doos dat een referentie wordt opgeslagen die nog eens 4 of 8 bytes vertegenwoordigt, afhankelijk van de JVM- en JVM-opties.

Bij gegevensintensieve bewerkingen kan geheugenconsumptie een grote invloed hebben op de prestaties. Het geheugenverbruik neemt nog meer toe bij gebruik van arrays: een float[5] array vereist slechts 32 bytes; terwijl een Float[5] die 5 verschillende niet-nulwaarden opslaat in totaal 112 bytes nodig heeft (op 64 bit zonder gecomprimeerde pointers neemt dit toe tot 152 bytes).

Caches met boxwaarde

De overheadkosten van de boxtypen kunnen tot op zekere hoogte worden beperkt door de caches met boxwaarden. Sommige van de boxtypen implementeren een cache van instanties. Standaard zal de klasse Integer bijvoorbeeld exemplaren in de cache opslaan om getallen in het bereik van -128 tot +127 . Dit vermindert echter niet de extra kosten die voortvloeien uit de extra geheugenindirection.

Als u een exemplaar van een type in een box maakt door autoboxing of door de statische methode value (of valueOf(primitive) aan te roepen, probeert het runtime-systeem een waarde in de cache te gebruiken. Als uw toepassing veel waarden gebruikt in het bereik dat in de cache is opgeslagen, kan dit de geheugenstraf van het gebruik van boxtypen aanzienlijk verminderen. Als u met de hand "boxed value-instanties" met de hand "maakt, is het beter om valueOf te gebruiken in plaats van new . (De new bewerking maakt altijd een nieuwe instantie.) Als het grootste deel van uw waarden zich echter niet in het cachegeheugen bevindt, kan het sneller zijn om new aan te roepen en het cachegeheugen op te slaan.

Primitieven omzetten

In Java kunnen we converteren tussen gehele waarden en waarden met drijvende komma. Omdat elk teken overeenkomt met een getal in de Unicode-codering, kunnen char typen ook worden geconverteerd van en naar de typen integer en floating-point. boolean is het enige primitieve datatype dat niet kan worden geconverteerd naar of van een ander primitief datatype.

Er zijn twee soorten conversies: verbredende conversie en versmallende conversie .

Een verbredende conversie is wanneer een waarde van het ene datatype wordt omgezet in een waarde van een ander datatype dat meer bits inneemt dan het vorige. Er is in dit geval geen sprake van gegevensverlies.

Dienovereenkomstig is een nauwere conversie wanneer een waarde van het ene gegevenstype wordt geconverteerd naar een waarde van een ander datatype dat minder bits in beslag neemt dan het vorige. In dit geval kan gegevensverlies optreden.

Java voert automatisch verbrede conversies uit . Maar als u een versmallingsconversie wilt uitvoeren (als u zeker weet dat er geen gegevensverlies zal optreden), kunt u Java dwingen de conversie uit te voeren met behulp van een taalconstructie die bekend staat als een cast .

Verbredende conversie:

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

Versmallende conversie:

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

Cheatsheet voor primitieve typen

Tabel met grootte en waardenbereik van alle primitieve typen:

data type numerieke weergave bereik van waarden standaardwaarde
boolean n / a vals en waar vals
byte 8-bit ondertekend -2 7 tot 2 7 - 1 0
-128 tot +127
kort 16-bit ondertekend -2 15 tot 2 15 - 1 0
-32.768 tot +32.767
int 32-bits ondertekend -2 31 tot 2 31 - 1 0
-2.147.483.648 tot +2.147.483.647
lang 64-bit ondertekend -2 63 tot 2 63 - 1 0L
-9.223.372.036.854.775.808 tot 9.223.372.036.854.775.807
vlotter 32-bit drijvend punt 1.401298464e-45 tot 3.402823466e + 38 (positief of negatief) 0.0F
dubbele 64-bit drijvend punt 4.94065645841246544e-324d tot 1.79769313486231570e + 308d (positief of negatief) 0.0D
verkolen 16-bit niet ondertekend 0 tot 2 16 - 1 0
0 tot 65.535

Opmerkingen:

  1. De Java Language Specification-mandaten die integrale typen ( byte tot long ) hebben ondertekend, gebruiken binaire twos-complementrepresentatie, en de drijvende komma types gebruiken standaard IEE 754 binaire drijvende komma representaties.
  2. Java 8 en hoger bieden methoden voor het uitvoeren van niet-ondertekende rekenkundige bewerkingen op int en long . Hoewel deze methoden kan een programma om de waarden van de respectievelijke types te behandelen als unsigned, de types blijven ondertekend types.
  3. Het kleinste drijvende punt dat hierboven wordt getoond, is subnormaal ; dat wil zeggen, ze hebben minder precisie dan een normale waarde. De kleinste normale getallen zijn 1.175494351e − 38 en 2.2250738585072014e − 308
  4. Een char vertegenwoordigt conventioneel een Unicode / UTF-16 code-eenheid .
  5. Hoewel een boolean slechts één bit informatie bevat, varieert de grootte in geheugen afhankelijk van de Java Virtual Machine-implementatie (zie Boolean-type ).


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow