Une variable est un emplacement de la mémoire dans lequel est stockée une valeur. Chaque variable porte une nom et c’est ce nom qui sert à identifier l’emplacement de la mémoire représenté par cette variable. Pour utiliser une variable, la première étape est la déclaration.
Déclarer une variable, c’est prévenir le compilateur qu’un nom va être
utilisé pour désigner un emplacement de la mémoire. En Java, on déclare
les variables à l’intérieur du bloc formé par les accolades du
main. Il faut toujours déclarer les variables avant de s’en
servir.
Nous ne travaillerons pour le moment que sur les variables de type
numérique entier. Le type qui y correspond, en Java est int.
On déclare les variables entières de la manière suivante :
public static void main(String[] args) { int variable1, variable2, ..., variablen; ... }
Cette instruction déclare les variables variable1, variable2, ..., variablen de type entier. Par exemple,
int variable1, variable2; int autrevariable1, autrevariable2;
Si on souhaite affecter à la variable v une valeur, on utilise l’opérateur =. Par exemple,
int v; v = 5;
Cet extrait de code déclare une variable de type entier que l’on
appelle v, puis lui affecte la valeur 5. Comme vous
venez de le voir, il est possible d’écrire directement dans le code
une valeur que l’on donne à une variable.
Il est aussi possible d’initialiser une variable en même temps qu’on la déclare. Par exemple, l’extrait ci-dessus se reformule
int v = 5;
Les opérations arithmétiques disponibles sont l’addition (+), la soustraction (-), la multiplication (*), la division entière dans l’ensemble des entiers relatifs (quotient : /, reste : %). Par exemple,
int v, w, z; v = 5; w = v + 1; z = v + w / 2; v = z % 3; v = v * 2;
Traduisons en Java l’instruction Saisir <variable> que nous avons vu en algorithmique. Pour récupérer la saisie d’un utilisateur et la placer dans une variable <variable>, on utilise l’instruction suivante :
Scanner <s> = new Scanner(System.in); <variable> = <s>.next<type>();
Il faut placer import java.util.Scanner; au début du fichier source pour que cette instruction fonctionne. et <s>.close(); une fois les saisies terminées.
Ne vous laissez pas impressionner par l’apparente complexité de cette instruction, elle suspend l’exécution du programme jusqu’à ce que l’utilisateur ait saisi une valeur et pressé la touche return. La valeur saisie est alors affetée à la variable <variable>. Par exemple, pour déclarer une variable i et l’initialiser avec une saisie, on procède comme suit :
Scanner tutu = new Scanner(System.in); int i = tutu.nextInt();
Il est possible par la suite de saisir d’autres variables sans avoir à redéclarer le Scanner.
float f = tutu.nextFloat();
Traduisons maintenant l’instruction Afficher <variable> en Java :
System.out.println(<variable>);
Cette instruction affiche la valeur contenue dans la variable variable.
Nous avons étendu, en algorithmique, l’instruction Afficher en intercalant des valeurs de variables entre les messages affichés. Il est possible de faire de même en Java :
System.out.println("la valeur de la variable v est " + v + ".");
Les valeurs ou variables affichées sont ici séparés par des +. Tout ce qui est délimité par des double quotes est affiché tel quel. Cette syntaxe s’étend à volonté :
System.out.println("les valeurs des variables x, y et z sont " + x + ", " + y + " et " + z);
Il est possible sous Eclipse, d’utiliser le raccourci sysout suivi de Ctrl+space.
Quatre types servent à représenter les entiers :
nom | taille (t) | nombre de valeurs (28t) |
byte | 1 octet | 28 valeurs |
short | 2 octet | 216 valeurs |
int | 4 octets | 232 valeurs |
long | 8 octets | 264 valeurs |
Il nécessaire en programmation de représenter des valeurs avec des 0 et des 1, même si Java s’en charge pour vous, il est nécessaire de savoir comme il procède pour comprendre ce qu’il se passe en cas de problème. On retrouve donc dans la mémoire la représentation binaire des nombres entiers. Ainsi la plage de valeur d’un byte, encodée en binaire, est :
{0000 0000, 0000 0001, 0000 0010, 0000 0011, …, 1111 1110, 1111 1111} |
Les nombres entiers positifs sont ceux qui commencent par un 0, ils sont représentés sur l’intervalle :
{0000 0000, 0000 0001, 0000 0010, 0000 0011, …, 0111 1100, 0111 1101, 0111 1110, 0111 1111} |
Les valeurs entières correspondantes sont :
{0, 1, 2, …, 125, 126, 127} |
Et les nombres négatifs, commençant par un 1, sont donc représentés sur l’intervalle :
{1000 0000, 1000 0001, 1000 0010, 1000 0011, …, 1111 1100, 1111 1101, 1111 1110, 1111 1111} |
Les nombres négatifs sont disposés du plus éloigné de 0 jusqu’au plus proche de 0, l’intervalle précédent code les valeurs :
{−27, −(27 − 1), −(27 − 2), −(27 − 3), …, −4, −3, −2, −1} |
Par conséquent, on représente avec un byte les valeurs
{−27, −(27 − 1), −(27 − 2), −(27 − 3), …, −4, −3, −2, −1, 0, 1, 2, …, 125, 126, 127} |
Les opérations arithmétiques sont exécutées assez bêtement, si vous calculez 0111 1111 + 0000 0001, ce qui correspond à (27 − 1) + 1, le résultat mathématique est 27, ce qui se code 1000 0000, ce qui est le codage de −27. Soyez donc attentifs, en cas de dépassement de capacité d’un nombre entier, vous vous retrouverez avec des nombres qui ne veulent rien dire. Si vous souhaitez faire des calculs sur des réels, un type flottant sera davantage adapté.
Le principe de représentation des entiers est le même sur tous les
types entiers. On résume cela dans le tableau suivant :
nom | taille (t) | nombre de valeurs (28t) | plus petite valeur | plus grande valeur |
byte | 1 octet | 28 valeurs | −27 | 27 − 1 |
short | 2 octet | 216 valeurs | −215 | 215 − 1 |
int | 4 octets | 232 valeurs | −231 | 231 − 1 |
long | 8 octets | 264 valeurs | −263 | 263 − 1 |
Les flottants servent à représenter les réels.
Leur nom vient du fait
qu’on les représente de façon scientifique : un nombre décimal (à
virgule) muni d’un exposant (un décalage de la virgule). Deux types
de base servent à représenter les flottants :
nom | taille |
float | 4 octet |
double | 8 octets |
Notez bien le fait qu’un point flottant étend le type à point fixe en permettant de "déplacer la virgule". Cela permet de représenter des valeurs très grandes ou très petites, mais au détriment de la précision. Nous examinerons dans les exercices les avantages et inconvénients des flottants.
Un littéral flottant s’écrit avec un point, par exemple l’approximation à 10−2 près de π s’écrit 3.14. Il est aussi possible d’utiliser la notation scientifique, par exemple le décimal 1 000 s’écrit 1e3, à savoir 1.103. Nous nous limiterons à la description du type float, le type double étant soumis à des règles similaires. Attention, les littéraux de type float s’écrivent avec un f en suffixe.
Le codage d’un nombre de type float (32 bits) est découpé
en trois parties :
partie | taille |
le bit de signe | 1 bit |
l’exposant | 8 bits |
la mantisse | 23 bits |
Le nombre est positif si le bit de signe est à 0, négatif si le bit de signe est à 1. La mantisse et l’exposant sont codés en binaire, la valeur absolue d’un flottant de mantisse m et d’exposant e est m/223.2e. Le plus grand entier qu’il est possible de coder sur 23 octets est (223 − 1), comme les bits de la mantisse représentent la partie décimale du nombre que l’on souhaite représenter, on obtient le plus grand nombre pouvant être représenté par la mantisse en divisant (223 − 1) par 223, soit (223 − 1)/223. Comme le plus grand exposant est 27 , le plus grand flottant est (223 − 1)/223.2(27), donc le plus petit est −(223 − 1)/223.2(27).
Un char sert à représenter le code UNICODE d’un caractère. Il est donc codé sur 2 octets. Il est possible d’affecter à une telle variable toute valeur du code UNICODE entourée de simples quotes. Par exemple, l’affectation suivante place dans a le code UNICODE du caractère ’B’.
char a; a = 'B';
Si une variable numérique entière e contient une valeur UNICODE, on obtient le caractère correspondant avec (char)e. Inversement, on obtient la valeur UNICODE d’une variable de type caractère c avec l’expression (int)c (où int peut être remplacé par n’importe quel type numérique entier d’au moins 2 octets).
Une chaîne de caractères, se déclarant avec le mot-clé String, est une succession de caractères (aucun, un ou plusieurs).
Les littéraux de ce type se délimitent par des double quotes, et l’instruction de saisie s’écrit sans le next() sans préciser le type. Par exemple,
String s = "toto"; String k = sc.next();