Java Language
Types de données primitifs
Recherche…
Introduction
byte
, short
, int
, long
, char
, boolean
, float
et double
sont les types qui stockent la plupart des données numériques brutes dans les programmes Java.
Syntaxe
int aInt = 8; // La partie définissant (nombre) de cette déclaration int est appelée un littéral.
int hexInt = 0x1a; // = 26; Vous pouvez définir des littéraux avec des valeurs hexadécimales préfixées par 0x .
int binInt = 0b11010; // = 26; Vous pouvez également définir des littéraux binaires; préfixé avec 0b .
long goodLong = 10000000000L; // Par défaut, les littéraux entiers sont de type int. En ajoutant le L à la fin du littéral, vous indiquez au compilateur que le littéral est long. Sans cela, le compilateur émettrait une erreur "nombre entier trop grand".
double aDouble = 3,14; // Les littéraux à virgule flottante sont de type double par défaut.
float aFloat = 3.14F; // Par défaut, ce littéral aurait été un double (et provoqué une erreur "Types incompatibles"), mais en ajoutant un F, nous indiquons au compilateur qu'il s'agit d'un flottant.
Remarques
Java a 8 types de données primitifs , à savoir boolean
, byte
, caractères short
, char
, int
, long
, float
et double
. (Tous les autres types sont des types de référence . Cela inclut tous les types de tableau et les types / classes d'objets intégrés qui ont une signification particulière dans le langage Java; par exemple, String
, Class
et Throwable
et ses sous-classes.)
Le résultat de l' ensemble des opérations (addition, soustraction, multiplication, etc) sur un type primitif est au moins un int
, ajoutant ainsi un short
à un short
produit un int
, tout comme l' ajout d' un byte
d'un byte
, ou une char
à une char
. Si vous souhaitez affecter le résultat à une valeur du même type, vous devez le lancer. par exemple
byte a = 1;
byte b = 2;
byte c = (byte) (a + b);
Ne pas lancer l'opération entraînera une erreur de compilation.
Cela est dû à la partie suivante de Java Language Spec, §2.11.1 :
Un compilateur encode des charges de valeurs littérales de types
byte
etshort
utilisant des instructions Java Virtual Machine qui étendent ces valeurs aux valeurs de typeint
à la compilation ou à l'exécution. Les charges de valeurs littérales des typesboolean
etchar
sont codées en utilisant des instructions qui étendent le littéral à zéro à une valeur de typeint
à la compilation ou à l'exécution. [..]. Ainsi, la plupart des opérations sur les valeurs des types réelsboolean
,byte
,char
etshort
sont effectuées correctement par des instructions fonctionnant sur des valeurs de type computationalint
.
La raison derrière cela est également spécifiée dans cette section:
Étant donné la taille de l'opcode un octet de la machine virtuelle Java, les types d'encodage en opcodes exercent une pression sur la conception de son jeu d'instructions. Si chaque instruction typée prenait en charge tous les types de données d'exécution de la machine virtuelle Java, il y aurait plus d'instructions que celles pouvant être représentées dans un
byte
. [...] Des instructions distinctes peuvent être utilisées pour convertir entre des types de données non pris en charge et pris en charge, selon les besoins.
La primitive int
Un type de données primitif tel que int
contient des valeurs directement dans la variable qui l'utilise, tandis qu'une variable déclarée à l'aide d' Integer
contient une référence à la valeur.
Selon l' API java : "La classe Integer encapsule une valeur du type primitif int dans un objet. Un objet de type Integer contient un seul champ dont le type est int."
Par défaut, int
est un entier signé 32 bits. Il peut stocker une valeur minimale de -2 31 et une valeur maximale de 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
Si vous devez stocker un nombre en dehors de cette plage, utilisez plutôt long
. Le dépassement de la plage de valeurs de int
conduit à un dépassement d'entier, ce qui entraîne l'ajout de la valeur supérieure à la plage sur le site opposé de la plage (le positif devient négatif et vice versa). La valeur est ((value - MIN_VALUE) % RANGE) + MIN_VALUE
ou ((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
Les valeurs maximales et minimales de int
peuvent être trouvées à:
int high = Integer.MAX_VALUE; // high == 2147483647
int low = Integer.MIN_VALUE; // low == -2147483648
La valeur par défaut d'un int
est 0
int defaultInt; // defaultInt == 0
La courte primitive
Un short
- short
est un entier signé de 16 bits. Il a une valeur minimale de 15 -2 (-32 768), et une valeur maximale de 2 15 -1 (32767)
short example = -48;
short myShort = 987;
short anotherShort = 17;
short addedShorts = (short) (myShort + anotherShort); // 1,004
short subtractedShorts = (short) (myShort - anotherShort); // 970
Les valeurs maximales et minimales de short
peuvent être trouvées à:
short high = Short.MAX_VALUE; // high == 32767
short low = Short.MIN_VALUE; // low == -32768
La valeur par défaut d'un short
est 0
short defaultShort; // defaultShort == 0
La longue primitive
Par défaut, long
est un entier signé de 64 bits (dans Java 8, il peut être signé ou non signé). Signé, il peut stocker une valeur minimale de -2 63 , et une valeur maximale de 2 63 - 1, et non signé il peut stocker une valeur minimale de 0 et une valeur maximale de 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
Les valeurs maximales et minimales de long
peuvent être trouvées à:
long high = Long.MAX_VALUE; // high == 9223372036854775807L
long low = Long.MIN_VALUE; // low == -9223372036854775808L
La valeur par défaut d'un long
est 0L
long defaultLong; // defaultLong == 0L
Note: la lettre "L" ajoutée à la fin du littéral long
est insensible à la casse, mais il est conseillé d’utiliser le majuscule car il est plus facile de le distinguer du chiffre 1:
2L == 2l; // true
Avertissement: Java met en cache les instances d'objets entiers de la plage allant de -128 à 127. Le raisonnement est expliqué ici: https://blogs.oracle.com/darcy/entry/boxing_and_caches_integer_valueof
Les résultats suivants peuvent être trouvés:
Long val1 = 127L;
Long val2 = 127L;
System.out.println(val1 == val2); // true
Long val3 = 128L;
Long val4 = 128L;
System.out.println(val3 == val4); // false
Pour comparer correctement 2 valeurs longues d'objet, utilisez le code suivant (à partir de Java 1.7):
Long val3 = 128L;
Long val4 = 128L;
System.out.println(Objects.equal(val3, val4)); // true
Comparer une longueur primitive à un objet long n'entraînera pas de faux négatif, par exemple en comparant 2 objets à ==.
La primitive booléenne
Un boolean
peut stocker une des deux valeurs, true
ou 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
La valeur par défaut d'un boolean
est false
boolean defaultBoolean; // defaultBoolean == false
La primitive d'octet
Un byte
est un entier signé de 8 bits. Il peut stocker une valeur minimale de -2 7 (-128) et une valeur maximale de 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
Les valeurs maximales et minimales de l' byte
sont disponibles à l'adresse suivante:
byte high = Byte.MAX_VALUE; // high == 127
byte low = Byte.MIN_VALUE; // low == -128
La valeur par défaut d'un byte
est 0
byte defaultByte; // defaultByte == 0
La primitive float
Un float
est un nombre à virgule flottante IEEE 754 32 bits à simple précision. Par défaut, les décimales sont interprétées comme des doubles. Pour créer un float
, ajoutez simplement un f
au littéral décimal.
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
Les flotteurs gèrent les cinq opérations arithmétiques courantes: addition, soustraction, multiplication, division et module.
Remarque: Les erreurs suivantes peuvent légèrement varier. Certains résultats ont été arrondis pour des raisons de clarté et de lisibilité (le résultat imprimé de l'exemple d'addition était en fait 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
En raison de la façon dont les nombres à virgule flottante sont stockés (c'est-à-dire sous forme binaire), de nombreux nombres n'ont pas de représentation exacte.
float notExact = 3.1415926f;
System.out.println(notExact); // 3.1415925
Bien que l'utilisation de float
soit appropriée pour la plupart des applications, ni float
ni double
ne doivent être utilisés pour stocker des représentations exactes de nombres décimaux (comme des montants monétaires) ou des nombres nécessitant une plus grande précision. Au lieu de cela, la classe BigDecimal
doit être utilisée.
La valeur par défaut d'un float
est 0.0f .
float defaultFloat; // defaultFloat == 0.0f
Un float
est précis à environ une erreur de 1 sur 10 millions.
Remarque: Float.POSITIVE_INFINITY
, Float.NEGATIVE_INFINITY
, Float.NaN
sont des valeurs float
. NaN
signifie les résultats des opérations qui ne peuvent pas être déterminés, tels que la division de 2 valeurs infinies. De plus, 0f
et -0f
sont différents, mais ==
donne une valeur vraie:
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
La double primitive
Un double
est un nombre à virgule flottante IEEE 754 64 bits à double précision.
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
En raison de la façon dont les nombres à virgule flottante sont stockés, beaucoup de nombres n'ont pas de représentation exacte.
double notExact = 1.32 - 0.42; // result should be 0.9
System.out.println(notExact); // 0.9000000000000001
Bien que l'utilisation du double
soit appropriée pour la plupart des applications, ni float
ni double
ne doivent être utilisés pour stocker des chiffres précis tels que la devise. Au lieu de cela, la classe BigDecimal
doit être utilisée
La valeur par défaut d'un double
est 0.0d
public double defaultDouble; // defaultDouble == 0.0
Remarque: Double.POSITIVE_INFINITY
, Double.NEGATIVE_INFINITY
, Double.NaN
sont double
valeurs double
. NaN
signifie les résultats des opérations qui ne peuvent pas être déterminés, tels que la division de 2 valeurs infinies. De plus, 0d
et -0d
sont différents, mais ==
donne une valeur vraie:
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
La primitive char
Un char
peut stocker un seul caractère Unicode 16 bits. Un littéral de caractère est placé entre guillemets simples
char myChar = 'u';
char myChar2 = '5';
char myChar3 = 65; // myChar3 == 'A'
Il a une valeur minimale de \u0000
(0 dans la représentation décimale, également appelée le caractère nul ) et une valeur maximale de \uffff
( \uffff
).
La valeur par défaut d'un char
est \u0000
.
char defaultChar; // defaultChar == \u0000
Afin de définir un produit de carbonisation de '
valeur d' une séquence d'échappement (caractère précédé d'une barre oblique inverse) doit être utilisée:
char singleQuote = '\'';
Il y a aussi d'autres séquences d'échappement:
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
Vous pouvez déclarer une char
de caractère Unicode.
char heart = '\u2764';
System.out.println(Character.toString(heart)); // Prints a line containing "❤".
Il est également possible d'ajouter à un char
. Par exemple, pour parcourir chaque lettre minuscule, vous pouvez effectuer les opérations suivantes:
for (int i = 0; i <= 26; i++) {
char letter = (char) ('a' + i);
System.out.println(letter);
}
Représentation de valeur négative
Java et la plupart des autres langages stockent des nombres intégraux négatifs dans une représentation appelée notation du complément 2 .
Pour une représentation binaire unique d'un type de données utilisant n
bits, les valeurs sont codées comme suit:
Les n-1
bits les moins significatifs stockent un nombre entier positif x
dans la représentation intégrale. La valeur la plus significative stocke un bit avec la valeur s
. La valeur représentée par ces bits est
x - s * 2 n-1
c'est-à-dire que si le bit le plus significatif est 1, alors une valeur juste supérieure de 1 au nombre que vous pourriez représenter avec les autres bits ( 2 n-2 + 2 n-3 + ... + 2 1 + 2 0 = 2 n-1 - 1
) est soustrait permettant une représentation binaire unique pour chaque valeur de - 2 n-1 (s = 1; x = 0) à 2 n-1 - 1 (s = 0; x = 2 n-1 - 1).
Cela a aussi l'effet secondaire agréable, que vous pouvez ajouter les représentations binaires comme s'il s'agissait de nombres binaires positifs:
v1 = x1 - s1 * 2n-1 v2 = x2 - s2 * 2n-1
s1 | s2 | débordement x1 + x2 | résultat supplémentaire |
---|---|---|---|
0 | 0 | Non | x1 + x2 = v1 + v2 |
0 | 0 | Oui | trop grand pour être représenté avec le type de données (débordement) |
0 | 1 | Non | x1 + x2 - 2n-1 = x1 + x2 - s2 * 2n-1 |
0 | 1 | Oui | (x1 + x2) mod 2n-1 = x1 + x2 - 2n-1 |
1 | 0 | * | voir ci-dessus (sommets de swap) |
1 | 1 | Non | trop petit pour être représenté avec le type de données (x1 + x2 - 2 n <-2 n-1 ; sous - dépassement) |
1 | 1 | Oui | (x1 + x2) mod 2n-1 - 2n-1 = (x1 + x2 - 2n-1) - 2n-1 |
Notez que ce fait facilite la recherche de représentation binaire de l'inverse additif (c'est-à-dire la valeur négative):
Observez que l'ajout du complément binaire au nombre a pour résultat que tous les bits sont 1. Maintenant, ajoutez 1 pour que la valeur soit dépassée et vous obtenez l'élément neutre 0 (tous les bits 0).
Donc, la valeur négative d'un nombre i
peut être calculée en utilisant (en ignorant la promotion possible à int
ici)
(~i) + 1
Exemple: en prenant la valeur négative de 0 ( byte
):
Le résultat de la négation 0
est 11111111
. L'ajout de 1 donne une valeur de 100000000
(9 bits). Un byte
ne pouvant stocker que 8 bits, la valeur la plus à gauche est tronquée et le résultat est 00000000
Original | Processus | Résultat |
---|---|---|
0 (00000000) | Nier | -0 (11111111) |
11111111 | Ajouter 1 au binaire | 100000000 |
100000000 | Tronquer à 8 bits | 00000000 (-0 est égal à 0) |
Consommation de mémoire des primitives vs primitives en boîte
Primitif | Type en boîte | Taille de la mémoire de la primitive / en boîte |
---|---|---|
booléen | Booléen | 1 octet / 16 octets |
octet | Octet | 1 octet / 16 octets |
court | Court | 2 octets / 16 octets |
carboniser | Carboniser | 2 octets / 16 octets |
int | Entier | 4 octets / 16 octets |
longue | Longue | 8 octets / 16 octets |
flotte | Flotte | 4 octets / 16 octets |
double | Double | 8 octets / 16 octets |
Les objets en boîte nécessitent toujours 8 octets pour la gestion des types et de la mémoire, et comme la taille des objets est toujours un multiple de 8, les types en boîte nécessitent un total de 16 octets . En outre , chaque utilisation d'un objet en boîte implique le stockage d'une référence qui représente 4 ou 8 octets supplémentaires , en fonction des options de la machine virtuelle Java et de la machine virtuelle Java.
Dans les opérations gourmandes en données, la consommation de mémoire peut avoir un impact majeur sur les performances. La consommation de mémoire augmente encore plus lorsque vous utilisez des tableaux: un tableau float[5]
ne nécessite que 32 octets; alors qu'un Float[5]
stockant 5 valeurs non nulles distinctes nécessitera un total de 112 octets (sur 64 bits sans pointeurs compressés, cela augmente à 152 octets).
Caches de valeur en boîte
Les frais généraux d'espace des types encadrés peuvent être atténués dans une certaine mesure par les caches de valeur encadrés. Certains types encadrés implémentent un cache d'instances. Par exemple, par défaut, la classe Integer
mettra en cache les instances pour représenter des nombres compris entre -128
et +127
. Cela ne réduit cependant pas le coût supplémentaire lié à l'indirection supplémentaire de la mémoire.
Si vous créez une instance d'un type en boîte soit par la mise en file d'attente automatique, soit en appelant la méthode statique valueOf(primitive)
, le système d'exécution tente d'utiliser une valeur mise en cache. Si votre application utilise beaucoup de valeurs dans la plage mise en cache, cela peut réduire considérablement la pénalité de mémoire liée à l'utilisation de types encadrés. Certes, si vous créez des instances de valeurs encadrées "à la main", il vaut mieux utiliser valueOf
plutôt que new
. (La new
opération crée toujours une nouvelle instance.) Si, toutefois, la majorité de vos valeurs ne se trouvent pas dans la plage mise en cache, il peut être plus rapide d'appeler new
et d'enregistrer la recherche de cache.
Conversion de primitifs
En Java, nous pouvons convertir entre des valeurs entières et des valeurs à virgule flottante. En outre, étant donné que chaque caractère correspond à un numéro dans le codage Unicode, char
types peuvent être convertis et des entiers et des types à virgule flottante. boolean
est le seul type de données primitif qui ne peut être converti en aucun autre type de données primitif.
Il existe deux types de conversions: l’ élargissement de la conversion et la réduction de la conversion .
Une conversion élargie se produit lorsqu'une valeur d'un type de données est convertie en une valeur d'un autre type de données qui occupe plus de bits que le premier. Il n'y a pas de problème de perte de données dans ce cas.
De manière correspondante, une conversion restreinte se produit lorsqu'une valeur d'un type de données est convertie en une valeur d'un autre type de données qui occupe moins de bits que le premier. La perte de données peut se produire dans ce cas.
Java effectue automatiquement des conversions élargies. Mais si vous souhaitez effectuer une conversion restreinte (si vous êtes certain qu'aucune perte de données ne se produira), vous pouvez forcer Java à effectuer la conversion en utilisant une structure de langage appelée cast
.
Conversion d'élargissement:
int a = 1;
double d = a; // valid conversion to double, no cast needed (widening)
Conversion rétrécie:
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
Types de primitives
Tableau indiquant la taille et la plage de valeurs de tous les types primitifs:
Type de données | représentation numérique | gamme de valeurs | valeur par défaut |
---|---|---|---|
booléen | n / a | faux et vrai | faux |
octet | 8 bits signés | -2 7 à 2 7 - 1 | 0 |
-128 à +127 | |||
court | 16 bits signé | -2 15 à 2 15 - 1 | 0 |
-32 768 à +32 767 | |||
int | 32 bits signés | -2 31 à 2 31 - 1 | 0 |
-2 147 483 648 à +2 147 483 647 | |||
longue | 64 bits signés | -2 63 à 2 63 - 1 | 0L |
-9.223.372.036.854.775.808 à 9.223.372.036.854.775.807 | |||
flotte | Virgule flottante 32 bits | 1.401298464e-45 à 3.402823466e + 38 (positif ou négatif) | 0,0F |
double | Virgule flottante 64 bits | 4.94065645841246544e-324d à 1.79769313486231570e + 308d (positif ou négatif) | 0.0D |
carboniser | 16 bits non signés | 0 à 2 16 - 1 | 0 |
0 à 65,535 |
Remarques:
- La spécification de langage Java stipule que les types intégraux signés (
byte
surlong
) utilisent la représentation binaire à double complément, et que les types à virgule flottante utilisent des représentations à virgule flottante binaire standard IEE 754. - Java 8 et versions ultérieures fournissent des méthodes pour effectuer des opérations arithmétiques non signées sur
int
etlong
. Bien que ces méthodes permettent à un programme de traiter les valeurs des types respectifs comme non signés, les types restent des types signés. - Le plus petit point flottant montré ci-dessus est sous - normal ; c'est-à-dire qu'ils ont moins de précision qu'une valeur normale . Les plus petits nombres normaux sont 1.175494351e − 38 et 2.2250738585072014e − 308
- Une
char
représente classiquement une unité de code Unicode / UTF-16. - Bien qu'un
boolean
contienne qu'un seul bit d'information, sa taille en mémoire varie en fonction de l'implémentation de Java Virtual Machine (voir le type booléen ).