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
byteetshortutilisant 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 typesbooleanetcharsont 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,charetshortsont 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 (
bytesurlong) 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
intetlong. 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
charreprésente classiquement une unité de code Unicode / UTF-16. - Bien qu'un
booleancontienne 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 ).