Java Language
Primitiva datatyper
Sök…
Introduktion
byte
, short
, int
, long
, char
, boolean
, float
och double
är de typer som lagrar mest råa numeriska data i Java-program.
Syntax
int aInt = 8; // Den definierande (nummer) delen av denna int-deklaration kallas en bokstavlig.
int hexInt = 0x1a; // = 26; Du kan definiera bokstäver med hexvärden förinställda med 0x .
int binInt = 0b11010; // = 26; Du kan också definiera binära bokstäver; förinställd med 0b .
länge braLång = 10000000000L; // Som standard är heltalslitteraler av typen int. Genom att lägga till L i slutet av det bokstavliga berättar du kompilatorn att bokstäverna är lång. Utan detta skulle kompilatorn kasta ett "heltal för stort" -fel.
dubbel aDouble = 3,14; // Flytande punktlitteraturer är av typen dubbel som standard.
float aFloat = 3,14F; // Som standard skulle denna bokstavliga ha varit ett dubbel (och orsakat ett "Inkompatibla typer" -fel), men genom att lägga till en F säger vi kompilatorn att det är en flottör.
Anmärkningar
Java har åtta primitiva datatyper , nämligen boolean
, byte
, short
, char
, int
, long
, float
och double
. (Alla andra typer är referenstyper . Detta inkluderar alla arraytyper och inbyggda objekttyper / klasser som har särskild betydelse för Java-språket; t.ex. String
, Class
och Throwable
och dess underklasser.)
Resultatet av alla operationer (tillägg, subtraktion, multiplikation, etc) på en primitiv typ är åtminstone ett int
, så att en short
till en short
ger en int
, liksom att lägga till en byte
till en byte
, eller en char
till en char
. Om du vill tilldela resultatet av det tillbaka till ett värde av samma typ, måste du kasta det. t.ex
byte a = 1;
byte b = 2;
byte c = (byte) (a + b);
Om du inte kastar operationen kommer det att leda till ett kompileringsfel.
Detta beror på följande del av Java Language Spec, §2.11.1 :
En kompilator kodar massor av bokstavliga värden av typer
byte
ochshort
hjälp av Java Virtual Machine-instruktioner som signerar-utökar dessa värden till värden av typint
vid kompileringstid eller körtid. Massor av bokstavliga värden av typenboolean
ochchar
kodas med hjälp av instruktioner som nollförlänger den bokstavliga till ett värde av typint
vid kompileringstid eller körtid. [..]. Således utförs de flesta operationer på värden på faktiska typerboolean
,byte
,char
ochshort
korrekt med instruktioner som arbetar med värden för beräkningstypint
.
Anledningen till detta anges också i det avsnittet:
Med tanke på Java Virtual Maskins en-byte-opkodstorlek , sätter kodningstyper till opcodes tryck på utformningen av dess instruktionsuppsättning. Om varje typad instruktion stödde alla Java Virtual Maskins runtime-datatyper skulle det finnas fler instruktioner än vad som kan representeras i en
byte
. [...] Separata instruktioner kan användas för att konvertera mellan datorstyper som inte stöds och stöds vid behov.
Den int primitiva
En primitiv datatyp som int
håller värden direkt i den variabel som använder den, medan en variabel som deklarerades med Integer
har en referens till värdet.
Enligt java API : "Integer-klassen lindar ett värde på den primitiva typen int i ett objekt. Ett objekt av typen Heltal innehåller ett enda fält vars typ är int."
Som standard är int
ett 32-bitars signerat heltal. Den kan lagra ett minimivärde av -2 31 och ett maxvärde på 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
Om du behöver lagra ett nummer utanför detta intervall, bör du använda long
istället. Överskridande av värdeintervallet för int
leder till ett heltalöverskridande, vilket orsakar att värdet överskrider intervallet läggs till motsatt plats i intervallet (positivt blir negativt och vice versa). Värdet är ((value - MIN_VALUE) % RANGE) + MIN_VALUE
eller ((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
Max- och minimivärden för int
kan hittas på:
int high = Integer.MAX_VALUE; // high == 2147483647
int low = Integer.MIN_VALUE; // low == -2147483648
Standardvärdet för en int
är 0
int defaultInt; // defaultInt == 0
Den korta primitiva
En short
är ett 16-bitars signerat heltal. Det har ett minimivärde av -2 15 (-32,768) och ett maximivärde av 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
Max- och minimivärdena för short
finns på:
short high = Short.MAX_VALUE; // high == 32767
short low = Short.MIN_VALUE; // low == -32768
Standardvärdet för en short
är 0
short defaultShort; // defaultShort == 0
Den långa primitiva
Som standard är long
ett 64-bitars signerat heltal (i Java 8 kan det antingen vara signerat eller osignerat). Undertecknad kan den lagra ett minimivärde av -2 63 , och ett maximivärde av 2 63 - 1, och utan signerad kan det lagra ett minimivärde av 0 och ett maximivärde av 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
Max- och minimivärden för long
finns på:
long high = Long.MAX_VALUE; // high == 9223372036854775807L
long low = Long.MIN_VALUE; // low == -9223372036854775808L
Standardvärdet för en long
är 0L
long defaultLong; // defaultLong == 0L
Obs: bokstaven "L" bifogad i slutet av long
bokstäver är falllöst känslig, men det är god praxis att använda kapital eftersom det är lättare att skilja från siffran ett:
2L == 2l; // true
Varning: Java-cacheminne Heltalsobjekt förekommer från intervallet -128 till 127. Motiveringen förklaras här: https://blogs.oracle.com/darcy/entry/boxing_and_caches_integer_valueof
Följande resultat kan hittas:
Long val1 = 127L;
Long val2 = 127L;
System.out.println(val1 == val2); // true
Long val3 = 128L;
Long val4 = 128L;
System.out.println(val3 == val4); // false
För att jämföra 2 Objekt Långa värden använder du följande kod (Från Java 1.7 och framåt):
Long val3 = 128L;
Long val4 = 128L;
System.out.println(Objects.equal(val3, val4)); // true
Att jämföra en primitiv lång med ett objekt lång kommer inte att resultera i ett falskt negativt som att jämföra två objekt med == gör.
Den booleska primitiva
En boolean
kan lagra ett av två värden, antingen true
eller 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
Standardvärdet för en boolean
är falskt
boolean defaultBoolean; // defaultBoolean == false
Den byte primitiva
En byte
är ett 8-bitars signerat heltal. Den kan lagra ett minimivärde av -2 7 (-128) och ett maximivärde av 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
Max- och minimivärden för byte
kan hittas på:
byte high = Byte.MAX_VALUE; // high == 127
byte low = Byte.MIN_VALUE; // low == -128
Standardvärdet för en byte
är 0
byte defaultByte; // defaultByte == 0
Float primitivt
En float
är ett 32-bitars IEEE 754-flytpunktsnummer med en enda precision. Som standard tolkas decimaler som dubbletter. För att skapa en float
bara lägga till en f
till decimalbokstäverna.
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 hanterar de fem vanliga aritmetiska operationerna: tillägg, subtraktion, multiplikation, delning och modul.
Obs: Följande kan variera något till följd av flytande punktfel. Vissa resultat har avrundats för tydlighet och läsbarhet (dvs. det tryckta resultatet av tilläggsexemplet var faktiskt 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
På grund av hur flytande punktnummer lagras (dvs. i binär form) har många nummer inte en exakt representation.
float notExact = 3.1415926f;
System.out.println(notExact); // 3.1415925
Även om det är bra att använda float
för de flesta applikationer, bör varken float
eller double
användas för att lagra exakta representationer av decimaltal (som monetära belopp) eller siffror där högre precision krävs. Istället BigDecimal
klassen BigDecimal
användas.
Standardvärdet för en float
är 0,0f .
float defaultFloat; // defaultFloat == 0.0f
En float
är exakt till ungefär ett fel på 1 av 10 miljoner.
Obs: Float.POSITIVE_INFINITY
, Float.NEGATIVE_INFINITY
, Float.NaN
är float
NaN
står för resultat av operationer som inte kan bestämmas, till exempel att dela två oändliga värden. Dessutom är 0f
och -0f
olika, men ==
ger sant:
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
Den dubbla primitiva
En double
är ett dubbelprecision 64-bitars IEEE 754 flytande punktnummer.
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
På grund av hur flytande punktnummer lagras har många nummer ingen exakt representation.
double notExact = 1.32 - 0.42; // result should be 0.9
System.out.println(notExact); // 0.9000000000000001
Även om du använder double
är bra för de flesta applikationer, bör varken float
eller double
användas för att lagra exakta siffror som valuta. Istället BigDecimal
klassen BigDecimal
användas
Standardvärdet för en double
är 0,0d
public double defaultDouble; // defaultDouble == 0.0
Obs: Double.POSITIVE_INFINITY
, Double.NEGATIVE_INFINITY
, Double.NaN
är double
värden. NaN
står för resultat av operationer som inte kan bestämmas, till exempel att dela två oändliga värden. Dessutom är 0d
och -0d
olika, men ==
ger sant:
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
Den röda primitiva
En char
kan lagra ett enda 16-bitars Unicode-tecken. En bokstavlig bokstav finns i enkla citat
char myChar = 'u';
char myChar2 = '5';
char myChar3 = 65; // myChar3 == 'A'
Det har ett \u0000
(0 i decimalrepresentationen, även kallad nolltecknet ) och ett maximivärde på \uffff
(65,535).
Standardvärdet för en char
är \u0000
.
char defaultChar; // defaultChar == \u0000
För att definiera en karaktär med '
värde måste en flygsekvens (tecken som föregås av ett backslash) användas:
char singleQuote = '\'';
Det finns också andra flykt-sekvenser:
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
Du kan förklara en char
av alla Unicode-karaktärer.
char heart = '\u2764';
System.out.println(Character.toString(heart)); // Prints a line containing "❤".
Det är också möjligt att lägga till en char
. till exempel för att upprepa alla små bokstäver, kan du göra följande:
for (int i = 0; i <= 26; i++) {
char letter = (char) ('a' + i);
System.out.println(letter);
}
Negativt värde representation
Java och de flesta andra språk lagrar negativa integrala nummer i en representation som kallas 2: s komplementnotation .
För en unik binär representation av en datatyp med hjälp av n
bitar kodas värdena så här:
De minst signifikanta n-1
bitarna lagrar ett positivt integralt antal x
i integrerad representation. Det mest betydande värdet lagrar lite med värdet s
. Värdet som repeteras av dessa bitar är
x - s * 2 n-1
dvs om den mest signifikanta biten är 1, då är ett värde som är bara 1 större än antalet du kan representera med de andra bitarna ( 2 n-2 + 2 n-3 + ... + 2 1 + 2 0 = 2 n-1 - 1
) subtraheras vilket tillåter en unik binär representation för varje värde från - 2 n-1 (s = 1; x = 0) till 2 n-1 - 1 (s = 0; x = 2 n-1 - 1).
Detta har också den trevliga bieffekten att du kan lägga till de binära representationerna som om de var positiva binära siffror:
v1 = x1 - s1 * 2n-1 v2 = x2 - s2 * 2n-1
s1 | s2 | x1 + x2 överflöde | tilläggsresultat |
---|---|---|---|
0 | 0 | Nej | x1 + x2 = v1 + v2 |
0 | 0 | Ja | för stor för att representeras med datatyp (översvämning) |
0 | 1 | Nej | x1 + x2 - 2n-1 = x1 + x2 - s2 * 2n-1 |
0 | 1 | Ja | (x1 + x2) mod 2n-1 = x1 + x2 - 2n-1 |
1 | 0 | * | se ovan (byta summands) |
1 | 1 | Nej | för liten för att representeras med datatyp (x1 + x2 - 2 n <-2 n-1 ; underflöde) |
1 | 1 | Ja | (x1 + x2) mod 2n-1 - 2n-1 = (x1 + x2 - 2n-1) - 2n-1 |
Observera att detta faktum gör det lätt att hitta binär representation av tillsatsen invers (dvs. det negativa värdet):
Observera att lägga till det bitvisa komplementet till antalet resulterar i att alla bitar är 1. Lägg nu till 1 för att göra överflödet av värde och du får det neutrala elementet 0 (alla bitar 0).
Så det negativa värdet på ett tal i
kan beräknas med (ignorera möjlig kampanj till int
här)
(~i) + 1
Exempel: ta det negativa värdet 0 ( byte
):
Resultatet av att negera 0
är 11111111
. Att lägga till 1 ger ett värde av 100000000
(9 bitar). Eftersom en byte
bara kan lagra 8 bitar, trunkeras det vänstra värdet och resultatet är 00000000
Original | Bearbeta | Resultat |
---|---|---|
0 (00000000) | Förneka | -0 (11111111) |
11111111 | Lägg till 1 i binär | 100000000 |
100000000 | Avkorta till 8 bitar | 00000000 (-0 är lika med 0) |
Minnesförbrukning av primitiva kontra boxade primitiva
Primitiv | Boxed Type | Minne Storlek på primitiv / låda |
---|---|---|
boolean | Boolean | 1 byte / 16 byte |
bitgrupp | byte | 1 byte / 16 byte |
kort | Kort | 2 byte / 16 byte |
röding | Röding | 2 byte / 16 byte |
int | Heltal | 4 byte / 16 byte |
lång | Lång | 8 byte / 16 byte |
flyta | Flyta | 4 byte / 16 byte |
dubbel- | Dubbel | 8 byte / 16 byte |
Boxade objekt kräver alltid 8 byte för typ- och minneshantering, och eftersom storleken på objekt alltid är en multipel av 8 kräver alla boxade typer 16 byte totalt . Dessutom innebär varje användning av ett boxat objekt att lagra en referens som står för ytterligare 4 eller 8 byte, beroende på JVM- och JVM-alternativ.
Vid datakrävande operationer kan minneskonsumtion ha stor inverkan på prestandan. Minneskonsumtionen växer ännu mer när du använder matriser: en float[5]
-grupp kräver endast 32 byte; medan en Float[5]
lagrar 5 distinkta icke-nollvärden kommer att kräva 112 byte totalt (på 64 bitar utan komprimerade pekare ökar detta till 152 byte).
Cacheminne för boxningsvärde
Rymdomkostnaderna för boxade typer kan mildras i viss utsträckning av cacheminnet med boxvärde. Vissa av de boxade typerna implementerar en cache av instanser. Till exempel, som Integer
kommer heltalsklassen att cache-instanser för att representera siffror i intervallet -128
till +127
. Detta minskar emellertid inte den extra kostnaden som uppstår till följd av den extra minnesdirektionen.
Om du skapar en instans av en boxad typ antingen genom autoboxing eller genom att anropa valueOf(primitive)
statisk valueOf(primitive)
försöker runtime-systemet att använda ett cache-värde. Om din applikation använder många värden i cache-cacheområdet kan det minska minnestraffet för att använda boxade typer avsevärt. Visst, om du skapar inställda värden i rutor "för hand", är det bättre att använda valueOf
snarare än new
. (Den new
åtgärden skapar alltid en ny instans.) Om huvuddelen av dina värden emellertid inte är i cacheområdet, kan det vara snabbare att ringa new
och spara cacheuppslaget.
Konvertera primitiv
I Java kan vi konvertera mellan heltalvärden och flytpunktsvärden. Eftersom alla tecken motsvarar ett nummer i Unicode-kodningen, kan char
typer också konverteras till och från heltal- och flytpunkttyperna. boolean
är den enda primitiva datatypen som inte kan konverteras till eller från någon annan primitiv datatyp.
Det finns två typer av omvandlingar: bredda konverteringen och minska konverteringen .
En utvidgad konvertering är när ett värde på en datatyp konverteras till ett värde på en annan datatyp som upptar fler bitar än den förra. Det finns ingen fråga om dataförlust i detta fall.
På motsvarande sätt är en minskande konvertering när ett värde på en datatyp konverteras till ett värde på en annan datatyp som upptar färre bitar än den förra. Dataförlust kan uppstå i detta fall.
Java utför utvidgade omvandlingar automatiskt. Men om du vill utföra en förminskande konvertering (om du är säker på att ingen dataförlust kommer att inträffa) kan du tvinga Java att utföra konverteringen med en språkkonstruktion som kallas en cast
.
Bredare konvertering:
int a = 1;
double d = a; // valid conversion to double, no cast needed (widening)
Begränsa konvertering:
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
Primitiva typer Cheatsheet
Tabell som visar storlek och värden för alla primitiva typer:
data typ | numerisk representation | värderingsintervall | standardvärde |
---|---|---|---|
boolean | n / a | falskt och sant | falsk |
bitgrupp | 8-bitars signerad | -2 7 till 2 7 - 1 | 0 |
-128 till +127 | |||
kort | 16-bitars signerad | -2 15 till 2 15 - 1 | 0 |
-32,768 till +32,767 | |||
int | 32-bitars signerad | -2 31 till 2 31 - 1 | 0 |
-2,147,483,648 till +2,147,483,647 | |||
lång | 64-bitars signerad | -2 63 till 2 63 - 1 | 0L |
-9,223,372,036,854,775,808 till 9,223,372,036,854,775,807 | |||
flyta | 32-bitars flytande punkt | 1.401298464e-45 till 3.402823466e + 38 (positiv eller negativ) | 0.0F |
dubbel- | 64-bitars flytande punkt | 4.94065645841246544e-324d till 1.79769313486231570e + 308d (positiv eller negativ) | 0.0D |
röding | 16-bitars osignerad | 0 till 2 16 - 1 | 0 |
0 till 65,535 |
Anmärkningar:
- Java-språkspecifikationen kräver att signerade integrerade typer (
byte
genomlong
) använder binär två-komplementrepresentation, och flytpunkttyperna använder standard IEE 754 binära flytpunktsrepresentationer. - Java 8 och senare tillhandahåller metoder för att utföra osignerade aritmetiska operationer på
int
ochlong
. Medan dessa metoder tillåter ett program att behandla värden för respektive typ som osignerade, förblir typerna signerade typer. - Den minsta flytande punkten som visas ovan är subnormal ; dvs de har mindre precision än ett normalt värde. De minsta normala siffrorna är 1.175494351e − 38 och 2.2250738585072014e − 308
- Ett
char
representerar konventionellt en Unicode / UTF-16- kodenhet . - Även om en
boolean
innehåller bara en bit information, varierar dess storlek i minnet beroende på Java Virtual Machine-implementeringen (se boolesktyp ).