Java Language
Primitieve gegevenstypen
Zoeken…
Invoering
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
enshort
met behulp van Java Virtual Machine-instructies die deze waarden tijdens de compilatie of runtime naar waarden van het typeint
uitbreiden. Tal van letterlijke waarden van de typenboolean
enchar
worden gecodeerd met behulp van instructies die de letterlijke waarde nul uitbreiden tot een waarde van het typeint
tijdens het compileren of uitvoeren. [..]. De meeste bewerkingen op waarden van werkelijke typenboolean
,byte
,char
enshort
worden dus correct uitgevoerd door instructies die werken op waarden van het computationele typeint
.
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 |
0 | 1 | Ja | (x1 + x2) mod 2n-1 = x1 + x2 - 2n-1 |
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 |
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:
- De Java Language Specification-mandaten die integrale typen (
byte
totlong
) hebben ondertekend, gebruiken binaire twos-complementrepresentatie, en de drijvende komma types gebruiken standaard IEE 754 binaire drijvende komma representaties. - Java 8 en hoger bieden methoden voor het uitvoeren van niet-ondertekende rekenkundige bewerkingen op
int
enlong
. Hoewel deze methoden kan een programma om de waarden van de respectievelijke types te behandelen als unsigned, de types blijven ondertekend types. - 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
- Een
char
vertegenwoordigt conventioneel een Unicode / UTF-16 code-eenheid . - Hoewel een
boolean
slechts één bit informatie bevat, varieert de grootte in geheugen afhankelijk van de Java Virtual Machine-implementatie (zie Boolean-type ).