L’auteur a sélectionné le Fonds Libre et Open Source pour recevoir une donation dans le cadre du programme Write for DOnations.
Introduction
Java est un langage de programmation à typage statique. Cela signifie que lors de la création d’une variable, vous devez également spécifier son type de données, qui est le type d’information qu’elle stocke. Cela contraste avec les langages à typage dynamique, tels que PHP. Avec les langages à typage dynamique, vous n’avez pas à spécifier le type de données d’une variable, ce qui peut sembler être un soulagement.
Cependant, connaître les types de données et les utiliser de manière appropriée permet aux développeurs d’optimiser leur code car chaque type de données a des exigences de ressources spécifiques. De plus, si vous spécifiez un type de données et essayez d’en stocker un autre, par erreur par exemple, vous ne pourrez pas compiler le code. Ainsi, avec les langages à typage statique, vous pouvez détecter les erreurs même avant tout test.
Java possède deux types de données: primitifs et de référence (également connus sous le nom de non primitifs). Dans ce tutoriel, vous utiliserez des variables pour stocker et utiliser des informations dans un programme Java afin d’apprendre certains des types de données couramment utilisés en Java. Ce n’est pas un aperçu exhaustif de tous les types de données, mais ce guide vous aidera à vous familiariser avec les options disponibles pour vous en Java.
Prérequis
Pour suivre ce tutoriel, vous aurez besoin de:
-
Un environnement dans lequel vous pouvez exécuter des programmes Java pour suivre les exemples. Pour le configurer sur votre machine locale, vous aurez besoin des éléments suivants :
- Java (version 11 ou supérieure) installé sur votre machine, avec le compilateur fourni par le Kit de développement Java (JDK). Pour Ubuntu et Debian, suivez les étapes de l’Option 1 de notre tutoriel, Comment installer Java avec Apt sur Ubuntu 22.04. Pour d’autres systèmes d’exploitation, y compris Mac et Windows, consultez les options de téléchargement pour l’installation de Java.
- Pour compiler et exécuter les exemples de code, ce tutoriel utilise Java Shell, une boucle Read-Evaluate-Print (REPL) exécutée à partir de la ligne de commande. Pour commencer avec JShell, consultez le guide Introduction à JShell.
-
Connaissance de Java et de la programmation orientée objet, que vous pouvez trouver dans notre tutoriel, Comment écrire votre premier programme en Java.
Types Primitifs
Java Les types primitifs sont les types de données les plus simples et fondamentaux en Java. Ils représentent des valeurs brutes telles que des nombres et des caractères. Les types de données primitifs les plus fréquemment utilisés sont int
(entiers), boolean
(valeurs booléennes) et char
(caractères). Vous pouvez trouver le reste dans la documentation officielle sur les types de données Java.
Entiers
Les entiers sont à la fois des nombres entiers négatifs et positifs. En Java, vous utiliserez int
pour les stocker. int
peut accommoder des nombres suffisamment grands pour la plupart des usages : de -2 147 483 648
à 2 147 483 647
.
Jetons un coup d’œil à la manière dont int
est utilisé dans un exemple :
int theAnswer = 42;
Les types primitifs commencent toujours par une lettre minuscule (int
). Les règles de syntaxe Java exigent que vous spécifiiez d’abord le type de données (int
) et ensuite son nom (theAnswer
). Ensuite, vous attribuez la valeur 42
avec le signe égal (=
) à la variable.
Quel que soit son type de données, vous utilisez une variable en spécifiant directement son nom sans ajouter de caractères spéciaux. Cela est possible car Java peut la reconnaître en tant que variable.
Remarque: Le nom de la variable theAnswer
et de toutes les autres variables de ce tutoriel sont écrites en Camel case. Bien qu’il n’y ait pas d’exigence stricte à cet égard, c’est la convention de nommage acceptée en Java.
Une fois que vous avez déclaré la variable, vous pouvez l’utiliser en la référençant dans une méthode comme ceci:
int theAnswer = 42;
System.out.println("The answer to all questions is " + theAnswer);
Dans la deuxième ligne, vous affichez theAnswer
dans la console en utilisant la méthode intégrée println
du package System.out
. C’est la manière la plus simple de tester une variable pour vérifier qu’elle est déclarée comme prévu.
Pour voir ce code en action, utilisez l’outil Java Shell. Après avoir installé Java, ouvrez un terminal ou une invite de commande sur votre ordinateur local et tapez jshell
:
- jshell
Votre sortie ressemblera à ce qui suit:
Output| Welcome to JShell -- Version 11.0.16
| For an introduction type: /help intro
jshell>
Vous pouvez coller les exemples de code de ce tutoriel dans la console. Une fois terminé, vous pouvez quitter jshell
en tapant /exit
.
Pour déclarer et utiliser int
, collez les lignes suivantes dans la console jshell
:
- int theAnswer = 42;
- System.out.println("The answer to all questions is " + theAnswer);
Vous verrez la sortie suivante:
OutputtheAnswer ==> 42
The answer to all questions is 42
Cette sortie confirme que vous avez correctement défini la variable int
theAnswer
sur 42 (theAnswer ==> 42
). Vous avez également réussi à utiliser theAnswer
en le passant à une méthode, et la méthode a produit la valeur de variable attendue.
Les valeurs Boolean
Boolean sont true
ou false
. En Java, vous utiliserez boolean
pour les stocker. Par exemple, créons une variable boolean
définissant si Java est amusant ou non:
boolean isJavaFun = true;
Vous définissez la variable isJavaFun
comme étant true
. La valeur alternative boolean
est false
.
En utilisant la variable ci-dessus, vous pouvez imprimer la phrase Java is fun: true
comme ceci:
- boolean isJavaFun = true;
- System.out.println("Java is fun: " + isJavaFun);
Exécuter ces lignes dans jshell
produira la sortie suivante:
OutputisJavaFun ==> true
Java is fun: true
Similaire à l’exemple avec int
, la méthode println
va imprimer l’argument fourni entre parenthèses. Le signe plus (+
) concatène ou joint la chaîne « Java is fun: » avec la variable isJavaFun
de sorte qu’en réalité, il s’agit d’un seul argument – la chaîne, Java is fun: true
.
Caractères
Pour stocker un seul caractère alphanumérique, vous utiliserez char
. Par exemple:
char firstLetter = 'a';
Remarquez que la lettre a
est entourée de guillemets simples. Les guillemets simples ne peuvent être utilisés que pour les valeurs char
. Les guillemets doubles sont utilisés pour les chaînes de caractères, comme vous le verrez plus tard.
char
ne semble pas être un type particulièrement utile car il est peu probable que vous ayez besoin d’une variable assignée à un seul caractère. Cependant, char
est utilisé comme élément de base pour les classes de chaînes de caractères telles que String
, qui sont essentiellement une collection de valeurs char
.
Comme vous l’avez vu dans cette section, la déclaration et l’utilisation de variables de type primitif sont simples car elles représentent des valeurs simples telles que des entiers. Ces valeurs sont prêtes à être utilisées et ne nécessitent pas d’opérations supplémentaires telles que la création d’objets, l’appel de méthodes, etc.
Types de référence
Dans le premier tutoriel de cette série, Comment écrire votre premier programme en Java, vous avez appris que le code Java est organisé en classes et que ces classes sont utilisées comme des modèles pour créer des objets. Lorsque de tels objets sont assignés à des variables, vous pointez ou faites référence à ces objets. Dans ces cas, les variables sont classifiées comme des types de référence. Ces variables sont également connues sous le nom de non primitifs car les variables de type primitif ne peuvent pas pointer vers des objets.
Les objets sont puissants car ils ont des propriétés avancées et sont capables d’agir lorsque vous déclenchez leurs méthodes. Cependant, sans variables pointant vers eux, ces objets sont inaccessibles et pratiquement inutilisables. C’est pourquoi les variables de type référence sont essentielles à Java et à la programmation orientée objet dans son ensemble.
Remarque : Les types de référence pointent vers des objets créés à partir de classes. Pour éviter toute confusion, le type de référence et l’objet créé seront de la même classe dans les exemples suivants.
Cependant, dans les programmes complexes, ce cas de figure est rarement rencontré. En Java, une interface est un groupe d’exigences pour un comportement spécifique, et ces exigences peuvent être satisfaites par une ou plusieurs classes. Une classe qui satisfait les exigences d’une interface est dite implémenter cette interface. Ainsi, dans les programmes complexes, il est courant de déclarer une variable avec le type de référence d’une interface. De cette manière, vous spécifiez le comportement que votre variable doit présenter sans la lier à une implémentation concrète de ce comportement. Cela vous permet de changer facilement l’implémentation vers laquelle votre variable pointe sans avoir à modifier la manière dont la variable est utilisée. Ce concept complexe fait partie d’un sujet plus avancé sur l’héritage et le polymorphisme, qui fera l’objet d’un tutoriel séparé dans notre série sur Java.
Bien qu’il n’y ait que quelques types primitifs, les types de référence sont pratiquement illimités car il n’y a pas de limite au nombre de classes (et interfaces), et chaque classe représente un type de référence. Il existe de nombreuses classes intégrées en Java qui fournissent des fonctionnalités essentielles. Les plus utilisées se trouvent dans le package principal java.lang
. Vous en passerez en revue certaines dans cette section.
La classe String
La classe String
représente une combinaison de caractères qui forment une chaîne de caractères. Pour déclarer une String
, ou toute autre variable de type référence, vous spécifiez d’abord son type suivi de son nom. Ensuite, vous lui attribuez une valeur avec le signe égal. Jusqu’à présent, c’est similaire à travailler avec des types primitifs. Cependant, les types de référence pointent vers des objets, vous devez donc créer un objet s’il n’en existe pas déjà un. Voici un exemple :
String hello = new String("Hello");
hello
est le nom de la variable de type référence String
. Vous l’assignez à un nouvel objet String
. Le nouvel objet String
est créé avec le mot-clé new
suivi du nom de la classe — String
dans ce cas. La classe String
commence par une lettre majuscule. Par convention, toutes les classes et donc les types de référence commencent par une lettre majuscule.
Chaque classe a une méthode spéciale appelée un constructeur qui est utilisée pour créer de nouveaux objets. Vous pouvez invoquer ce constructeur en ajoutant des parenthèses (()
) à la fin du nom de la classe. Le constructeur peut accepter des paramètres, comme dans l’exemple ci-dessus, où le paramètre "Hello"
est appliqué au constructeur pour String
.
Pour confirmer que la variable hello
se comporte comme prévu, passez-la à nouveau à la méthode println
comme ceci :
- String hello = new String("Hello");
- System.out.println(hello);
En exécutant ces lignes dans jshell
, vous obtiendrez la sortie suivante :
Outputhello ==> "Hello"
Hello
Cette fois, la sortie confirme que la variable hello
est définie sur Hello
. Ensuite, ce même Hello
est imprimé sur une nouvelle ligne, confirmant que la méthode println()
l’a traité.
Classes d’enveloppe
Dans la section précédente, vous avez travaillé avec le type de référence String
, qui est fréquemment utilisé. D’autres types de référence populaires sont les enveloppes pour les types primitifs, appelées ainsi. Une classe d’enveloppe enveloppe ou contient des données primitives, d’où son nom. Tous les types primitifs ont des équivalents d’enveloppe, et voici quelques exemples :
Integer
: Pour envelopper les valeursint
.Character
: Pour envelopper les valeurschar
.Boolean
: Pour envelopper les valeursboolean
.
Ces enveloppes existent afin que vous puissiez améliorer une valeur primitive simple en un objet puissant. Chaque enveloppe a des méthodes prêtes à l’emploi liées aux valeurs qu’elle est conçue pour stocker.
À titre d’exemple, vous explorerez Integer
. Dans la section précédente, vous avez créé un objet String
avec le mot-clé new
. Cependant, certaines classes fournissent, voire encouragent, l’utilisation de méthodes spéciales pour obtenir des objets à partir d’elles, et Integer
en est une. Dans le cas de Integer
, l’utilisation d’une méthode spéciale concerne principalement l’optimisation des ressources, mais dans d’autres cas, il pourrait s’agir de simplifier la construction d’objets complexes.
Dans l’exemple suivant, vous créez une variable Integer
appelée theAnswer
avec la valeur 42
en utilisant la méthode valueOf
:
- Integer theAnswer = Integer.valueOf(42);
- System.out.println(theAnswer);
Dans jshell
, vous obtiendrez la sortie suivante:
OutputtheAnswer ==> 42
42
En invoquant la méthode valueOf(42)
de la classe Integer
, vous indiquez à Java de vous fournir un objet avec cette valeur. En coulisses, Java vérifiera s’il existe déjà un objet avec une telle valeur dans son cache. S’il existe, l’objet sera lié à la variable theAnswer
. S’il n’y en a pas, un nouvel objet sera créé pour la variable theAnswer
.
De nombreuses classes intégrées fournissent de telles méthodes pour des raisons de performances, et leur utilisation est recommandée, voire obligatoire. Dans le cas de Integer
, vous pourriez toujours créer un objet avec le mot-clé new
, mais vous obtiendrez un avertissement de dépréciation.
En plus de String
et des wrappers, il existe également d’autres types de référence intégrés utiles, que vous pouvez trouver dans le résumé du package java.lang. Pour comprendre pleinement certains de ces types de référence plus avancés, une explication supplémentaire ou des connaissances préalables sont nécessaires. C’est pourquoi nous en couvrirons certains dans nos prochains tutoriels de la série Java.
Littéraux
Les littéraux représentent des valeurs fixes qui peuvent être utilisées directement dans le code et peuvent donc être assignées à la fois aux types primitifs et de référence. Il existe quelques types de littéraux, qui peuvent être catégorisés comme suit.
Littéraux de type primitif
Vous avez déjà utilisé quelques littéraux dans la section sur les types primitifs. Pour chaque type primitif, il existe un littéral, comme ceux de nos exemples: 42
, 'a'
, et true
. Les entiers tels que 42
sont des littéraux entiers. De même, les caractères tels que 'a'
sont des littéraux de caractère, et true
et false
sont des littéraux booléens.
Les littéraux des types primitifs peuvent également être utilisés pour créer des valeurs pour les types de référence. Le littéral int
a été utilisé pour créer un objet Integer
avec le code Integer.valueOf(42)
. Il existe également une version abrégée pour cela, et vous pouvez assigner directement la valeur comme ceci :
Integer theAnswer = 42;
42
est un littéral entier, tout comme n’importe quel nombre entier, et vous pouvez l’assigner directement à la variable theAnswer
sans aucune instruction supplémentaire. Il est courant de voir un Integer
déclaré de cette manière car c’est pratique.
Cette approche abrégée fonctionne également pour d’autres littéraux de types primitifs et leurs types de référence correspondants tels que Boolean
, par exemple :
Boolean isFun = true;
true
est le littéral, qui est directement assigné à la variable isFun
de type Boolean
. Il existe également un littéral false
, que vous pouvez assigner de la même manière.
Le littéral de chaîne de caractères
Il existe également un littéral spécial pour le type de référence String
, et il est reconnu par les guillemets doubles entourant sa valeur. Dans cet exemple, c’est "Hello, World!"
:
String helloWorld = "Hello, World!";
L’utilisation de littéraux est plus simple et plus courte, et c’est pourquoi de nombreux programmeurs le préfèrent. Cependant, vous pouvez toujours déclarer une variable String
avec un nouvel objet String
, comme vous l’avez déjà fait dans la section des types de référence.
Le littéral Null
Il y a un autre littéral important: null
, qui représente l’absence d’une valeur ou la non-existence d’un objet. Null
vous permet de créer un type de référence et de le pointer vers null
au lieu de le pointer vers un objet. null
peut être utilisé pour tous les types de référence mais pas pour les types primitifs.
Il y a une mise en garde avec le littéral null
: vous pouvez déclarer des variables avec, mais vous ne pouvez pas utiliser ces variables tant que vous n’avez pas réassigné une valeur appropriée et non nulle. Si vous essayez d’utiliser une variable de type de référence avec une valeur null
, vous obtiendrez une erreur. Voici un exemple:
- String initiallyNullString = null;
- System.out.println("The class name is: " + initiallyNullString.getClass());
Lorsque vous essayez d’exécuter ce code dans jshell
, vous verrez une erreur similaire à la suivante:
OutputinitiallyNullString ==> null
| Exception java.lang.NullPointerException
| at (#4:1)
En fonction de votre système d’exploitation et de votre version de Java, votre sortie peut différer.
L’erreur java.lang.NullPointerException
est lancée parce que vous essayez d’invoker la méthode getClass()
de String
(qui retourne le nom de la classe) sur la variable initiallyNullString
(qui pointe vers un objet nul).
Note: Pour simplifier, nous appelons java.lang.NullPointerException
une erreur même si c’est techniquement une exception. Pour en savoir plus sur les exceptions et les erreurs, consultez le tutoriel, Gestion des exceptions en Java.
Pour corriger l’erreur, vous devez réaffecter la valeur de initiallyNullString
comme ceci:
- String initiallyNullString = null;
- initiallyNullString = "not null any longer";
- System.out.println("The class name is: " + initiallyNullString.getClass());
Le nouveau code corrigé affichera la sortie suivante:
OutputinitiallyNullString ==> null
initiallyNullString ==> "not null any longer"
The class name is: class java.lang.String
La sortie ci-dessus montre comment initiallyNullString
est d’abord null
, puis devient un nouvel objet String
contenant "not null any longer"
. Ensuite, lorsque la méthode getClass()
est invoquée sur l’objet instancié, vous obtenez java.lang.String
, où String
est le nom de la classe et java.lang
est son package. Enfin, un message complet et significatif est imprimé: "Le nom de la classe est: class java.lang.String"
.
De telles déclarations de valeurs null
sont plus courantes pour le code hérité. Elles ont été utilisées pour créer d’abord une variable, puis plus tard pour lui assigner sa vraie valeur, généralement en passant par une logique qui détermine cette dernière. Cependant, depuis la version 8 de Java, il existe un nouveau type de référence appelé Optionnel, qui est plus adapté aux cas où null
a été utilisé auparavant.
Inférence de type de variable locale
Jusqu’à présent, vous avez utilisé certains des types de données courants en Java pour définir des variables. Cependant, Java 10 a introduit une nouvelle fonctionnalité appelée inférence de type de variable locale, qui vous permet d’utiliser le mot-clé var
devant une nouvelle variable. Avec cette fonctionnalité, Java inférera (c’est-à-dire, devinera automatiquement) le type de données à partir du contexte local. L’inférence de type est controversée car elle contraste avec la verbosité précédemment expliquée de la définition des variables. Les avantages et les inconvénients d’une telle fonctionnalité sont discutables, mais le fait est que d’autres langages typés statiquement, tels que le C++, prennent en charge l’inférence de type.
En tout cas, l’inférence de type ne peut pas remplacer complètement l’utilisation des types de données car elle ne fonctionne qu’avec les variables locales, qui sont des variables à l’intérieur d’une méthode. Regardons un exemple avec var
:
- var hello = "Hello";
- System.out.println(hello);
Vous déclarez la variable hello
avec le mot-clé var
afin d’instruire Java de détecter son type de données. Ensuite, vous l’imprimez dans la console de la manière habituelle pour confirmer qu’elle fonctionne comme prévu:
Ouputhello ==> "Hello"
Hello
Cet exemple fonctionnera tant que votre installation Java (plus précisément, le JDK) est supérieure à la version 10. Le mot-clé var
n’est pas pris en charge dans les versions plus anciennes.
L’inférence de type se produit pendant le processus de compilation, c’est-à-dire lorsque vous compilez le code. Le processus de compilation transforme le code source en texte brut en code machine et applique diverses optimisations, y compris l’inférence de type. Cela garantit que la quantité correcte de mémoire système est disponible pour les variables dont le type est inféré. Ainsi, le code machine que vous exécutez après la compilation est entièrement optimisé, comme si vous aviez spécifié manuellement tous les types de données.
Dans cet exemple, le mot-clé var
fonctionne car la variable est locale, et le type de données var
ne fonctionne qu’avec les variables locales. Les variables locales sont définies à l’intérieur des méthodes et sont accessibles uniquement à l’intérieur des méthodes, c’est pourquoi elles sont appelées « locales ».
Pour montrer que var
ne peut être utilisé que pour les variables locales, essayez de le placer en dehors de la méthode principale, comme ceci :
- public class Hello {
- var hello = "Hello";
- public static void main(String[] args) {
- // example code
- }
- }
Lorsque vous collez le code ci-dessus dans jshell
, vous obtiendrez l’erreur suivante :
Output| Error:
| 'var' is not allowed here
| var hello = "Hello";
| ^-^
var
n’est pas autorisé ici car hello
est en dehors d’une méthode et n’est plus considéré comme local. Ainsi, l’inférence de type ne fonctionne pas pour les variables non locales car le contexte ne peut pas être utilisé de manière fiable pour détecter le type de données.
Utiliser var
peut être difficile et n’est pas nécessaire, mais vous risquez probablement de le rencontrer, il est donc utile de le connaître.
Mots-clés réservés
Lorsque vous déclarez des variables en Java, il y a une règle supplémentaire importante à connaître. Il existe des mots-clés réservés que vous ne pouvez pas utiliser comme noms de variables. Par exemple, vous ne pouvez pas déclarer une primitive de type int
et l’appeler new
comme ceci:
- int new = 1;
Si vous essayez cet exemple, vous obtiendrez des erreurs de compilation car new
est un mot-clé réservé.
Output| Error:
| '.class' expected
| int new = 1;
| ^
| Error:
| <identifier> expected
| int new = 1;
| ^
| Error:
| '(' or '[' expected
| int new = 1;
| ^
| Error:
| unexpected type
| required: value
| found: class
| int new = 1;
| ^--^
| Error:
| missing return statement
| int new = 1;
| ^----------^
Le mot-clé new
est utilisé pour créer de nouveaux objets et Java ne s’attend pas à le trouver à cette position. Dans la liste des erreurs dans la sortie précédente, la première partie est la plus importante:
Output| Error:
| '.class' expected
| int new = 1;
| ^
L’erreur '.class' expected
signifie que lorsque vous utilisez le mot-clé new
, Java s’attend à ce qu’une classe suive. À ce stade, Java n’est pas en mesure d’interpréter l’instruction et les autres erreurs suivent.
Le reste des mots-clés réservés, tels que abstract
, continue
, default
, for
et break
, ont également des significations spécifiques en Java et ne peuvent pas être utilisés comme noms de variables. La liste complète des mots-clés réservés peut être trouvée sur la page Mots-clés du langage Java. Même si vous ne vous souvenez pas de tous les mots-clés réservés, vous pouvez utiliser les erreurs de compilation pour identifier le problème.
Conclusion
Dans ce tutoriel, vous avez appris les types de données primitifs et de référence en Java, qui est un sujet complexe mais essentiel. Prenez votre temps pour le pratiquer et passez en revue les exemples plus d’une fois. Essayez de changer certains types de données et valeurs. Soyez attentif aux moments où des erreurs sont générées et quand elles ne le sont pas afin de développer un sentiment d’exécution réussie du code.
Pour en savoir plus sur Java, consultez notre série Comment Coder en Java.
Source:
https://www.digitalocean.com/community/tutorials/understanding-data-types-in-java