Rechercher
 

Synthèse sur les opérateurs Java

Les types de données Les instructions



Accès rapide :
Les opérateurs de transtypage (cast operators)
Les opérateurs arithmétiques
Les opérateurs logiques
Les opérateurs de comparaisons
Les opérateurs d'affectations
Les opérateurs travaillant sur les chaînes de caractères
Les autres opérateurs Java
La table de précédence des opérateurs Java

Vos programmes Java vont, logiquement, calculer un certain nombre d'expressions. Une expression est constituée d'opérateurs et d'opérandes. Ainsi l'expression 3 + 4 est basée sur l'opérateur + et mais en jeux les opérandes 3 et 4. Le résultat de cette expression (très simple) valant bien entendu 7. Comme nous allons le voir, le langage Java propose un très grand nombre d'opérateurs : ils sont, en très grosse partie, récupérés du langage de programmation C. Nous allons tout au long de ce chapitre présenter l'utilisation des principaux opérateurs de langage à grand renfort d'exemples de code Java.

Les opérateurs de transtypage (cast operators)

Les opérateurs de transtypage (pour la suite, je préférerai la terminologie anglo-saxonne d'opérateurs de cast). Permettent de transformer une donnée d'un type en une donnée d'un autre type. On peut utiliser des opérateurs de cast explicites ou implicites, selon qu'il y ait ou non, une perte d'information durant la transformation. Par exemple si vous cherchez à transformer un double en un float, on passe d'un type plus précis à un type moins précis : l'utilisation d'un cast implicite est donc obligatoire pour confirmer l'éventuelle perte de précision. Dans l'autre sens, le cast est implicite (vous pouvez néanmoins explicitement l'écrire).

Syntaxiquement parlant, on reconnait un opérateur de cast par le fait qu'il est obligatoirement entre parenthéses et que son nom est obligatoirement un nom de type. L'exemple ci-dessous vous montre quelques exemples de cast : les casts implicites sont repérés par la présence du cast sous forme d'un commentaire (il est néanmoins présent de par son aspect implicite).

 
01 public class TestCasts  {
02 
03     public static void main( String [] args ) {
04                 
05         // cinq cast implicites : on passe d'un type plus
06         // petit vers un type plus grand
07         byte    byteValue   = 111;
08         short   shortValue  = /* (short) */ byteValue;
09         int     intValue    = /* (int) */ shortValue;
10         long    longValue   = /* (long) */ intValue;
11         float   floatValue  = /* (float) */ intValue;
12         double  doubleValue = /* (double) */ longValue;
13         
14         // Cinq cast explicites : si vous ne les mettez
15         // pas, des erreurs vous seront retournées.
16         doubleValue = 12345678901.123456789;
17         floatValue  = (float) doubleValue;   // vous acceptez la perte de précision
18         longValue   = (long) doubleValue;    // Idem
19         intValue    = (int) longValue;       // Idem
20         shortValue  = (short) intValue;      // Idem
21         byteValue   = (byte) shortValue;     // Idem
22         
23         System.out.println( doubleValue );
24         System.out.println( floatValue );
25         System.out.println( longValue );
26         System.out.println( intValue );
27         System.out.println( shortValue );
28         System.out.println( byteValue );
29         
30     }
31 
32 }

Les opérateurs arithmétiques

Les opérateurs arithmétiques permettent, bien entendu, de constituer des expressions arithmétiques. Ces opérateurs sont quasiment utilisant sur tous les types numériques (byte, short, int, long, float et double). Ces opérateurs sont au nombre de cinq : + (pour l'addition), - (pour la soustraction), * (pour la multiplication), / (pour la division) et % (pour le reste de la division entière). L'exemple qui suit vous montre quelques exemples d'utilisations des opérateurs arithmétiques.

 
01 public class TestOperators  {
02 
03     public static void main( String [] args ) {
04                 
05         int  first = 9;
06         int second = 4;
07         int result;
08         
09         result = first + second;    // Calcule 13
10         System.out.println( "9+4 == " + result );
11 
12         result = first - second;    // Calcule 5
13         System.out.println( "9-4 == " + result );
14 
15         result = first * second;    // Calcule 36
16         System.out.println( "9*4 == " + result );
17 
18         result = first / second;    // Calcule 2
19         System.out.println( "9/4 == " + result );
20 
21         result = first % second;    // Calcule 1
22         System.out.println( "9%4 == " + result );
23 
24     }
25 
26 }

Méfiez-vous néanmoins des opérateurs / et % : leur comportement dépend que l'on travaille sur des types entiers ou des types flottants. Effectivement, une source d'erreur classique est la suivante : l'opérateur /, s'il est invoqué avec deux entiers renverra, obligatoirement, une valeur entière. L'exemple ci-dessous vous mets face à la problématique.

 
01 public class TestOperators  {
02 
03     public static void main( String [] args ) {
04                 
05         // Calcule la valeur 0, car nous avons demandé la division entière !!!
06         // La valeur est transformée en double APRES le calcul.
07         double firstResult = 1 / 3;
08         System.out.println( "1/3 == " + firstResult );
09 
10         // Calcule la valeur 0.3333333432674408 (division flottante simple précision) 
11         double secondResult = 1 / (float)3;  // ou secondResult = 1 / 3.0f;
12         System.out.println( "1/(float)3 == " + secondResult );
13 
14         
15         // Calcule la valeur 0.3333333333333333 (division flottante double précision) 
16         double thirdResult = 1 / (double)3;  // ou secondResult = 1 / 3.0;
17         System.out.println( "1/(double)3 == " + thirdResult );
18         
19     }
20 
21 }

Si vous mixez deux types distincts lors de l'utilisation d'un opérateur arithmétique, c'est toujours le type le plus large qui l'emporte : 3 + 3.6 calcule une valeur de type double et non entière. Enfin, notez qu'il existe un ordre de priorité entre les différents opérateurs : la dernière partie de ce chapitre vous présentera la table de précédence des opérateurs Java. L'utilisation des parenthèses vous permettra d'influer sur l'ordre d'évaluation de vos opérateurs. L'exemple qui suit vous montre ces points par l'exemple.

 
01 public class TestOperators  {
02 
03     public static void main( String [] args ) {
04                 
05         double doubleResult = 3L + 3.5;
06         System.out.println( "3L+3.5 == " + doubleResult );
07         
08         
09         float floatResult = (float)(3 + 3.5);
10         System.out.println( "(float)(3+3.5) == " + floatResult );
11         
12         
13         int intResult1 = 3 + 2 * 4;     // calcule 11 
14         int intResult2 = (3 + 2) * 4;   // calcule 20 
15         System.out.println( intResult1 + " / " + intResult2 );
16         
17     }
18 
19 }

Les opérateurs logiques

Les opérateurs logiques acceptent obligatoirement des opérandes booléens et calculent un résultat booléen. Ils sont très fortement utilisés dans instructions de tests (if ou switch) et dans les instructions de boucles (notamment pour terminer une boucle). Ils sont au nombre de trois : && (le et logique), || (pour le ou logique) et le ! (pour le non logique).

 
01 public class TestOperators  {
02 
03     public static void main( String [] args ) {
04 
05         boolean debugMode = false;
06         
07         if ( args.length>0 && args[0].equals("debug") ) {
08             debugMode = true;
09             System.out.println( "Le mode debug est activé" );
10         }
11 
12         if ( ! debugMode ) {
13             System.out.println( "Action a ne pas faire en mode debug" );
14         }
15     }
16     
17 }

Les opérateurs de comparaisons

Les opérateurs de comparaisons permettent, comme vous vous en doutez, de réaliser des comparaisons entre des données. Il y a six opérateurs de comparaison : == (pour le test d'égalité), != (pour le test de non-égalité), <= (pour le test d'infériorité), < (pour le test d'infériorité stricte), >= (pour le test de supériorité) et enfin > (pour le test de supériorité stricte). Voici un petit exemple d'utilisation de ces opérateurs.

 
01 public class TestOperators  {
02 
03     
04     public static void main( String [] args ) {
05 
06         if ( args.length == 0 ) {
07             System.out.println( "Usage: java TestOperators age" );
08             System.exit( 0 );
09         }
10         
11         int age = Integer.parseInt( args[0] );
12         
13         if ( age < 18 ) {
14             System.out.println( "Vous êtes mineur" );
15             System.exit( 0 );
16         }
17 
18         if ( age >= 18 && age <= 65 ) {
19             System.out.println( "Vous êtes certainement actif" );
20             System.exit( 0 );
21         }
22         
23         if ( age < 100 ) {
24             System.out.println( "Vous êtes certainement à la retraite" );
25             System.exit( 0 );
26         }
27     
28         System.out.println( "Alors là, respect !" );
29         
30     }
31     
32 }

Les opérateurs d'affectations

Tous les langages dérivés du langage C (C++, Java bien entendu, Javascript, C#, ...) présentent une caractéristique remarquable : contrairement aux autres langages (pascal, ...), l'affectation n'est pas une instruction mais bien un opérateur. Il en découle que l'affectation calcule une valeur, à savoir la valeur affectée. L'exemple suivant vous montre deux manières d'exploiter cette possibilité. En ligne 07, plusieurs affectation sont cascadées : l'ordre d'associativité de l'opérateur est de la droite vers la gauche (on affecte 0 à e - le résultat est 0 que l'on affecte à d - et ainsi de suite ...). En ligne 14, on affecte une valeur à une position d'un tableau : le résultat de cette affectation est encore une fois la valeur affectée. Du coup, on se sert de cette valeur pour calculer la condition de sortie de la boucle while.

 
01 public class TestOperators {
02 
03     public static void main( String [] args ) {
04 
05         // On peut cascader les affectations
06         int a, b, c, d, e;
07         a = b = c = d = e = 1;
08         int somme = a + b + c + d + e;        // Calcule 5
09         System.out.println( "Somme == " + somme );
10         
11         // On peut se servir d'une affectation comme valeur de test
12         int [] tableau = new int[ 5 ];
13         int position = 0;
14         while ( ( tableau[ position ] = position ) != 4 ) {
15             position ++;
16         }
17         
18         for( position=0; position<5; position++ ) {
19             System.out.println( tableau[ position ] );
20         }
21         
22     }
23     
24 }

Notez que l'opérateur = n'est pas le seul opérateur permettant de modifier le contenu d'une variable : à l'instar du langage C, de nombreux opérateurs permettent de coupler une opération avec une affectation. Le tableau ci-dessous liste l'ensemble de ces opérateurs. Notez aussi la présence des opérateurs ++ et -- qui permettent de réaliser, respectivement, une incrémentation et une décrémentation.

Opérateur Explications complémentaires
+=  Ex: a += 2;         équivaut quasiment à         a = a + 2;
-=  Ex: a -= 2;         équivaut quasiment à         a = a - 2;
*=  Ex: a *= 2;         équivaut quasiment à         a = a * 2;
/=  Ex: a /= 2;         équivaut quasiment à         a = a / 2;
%=  Ex: a %= 2;         équivaut quasiment à         a = a % 2;
&=  Ex: a &= 2;         équivaut quasiment à         a = a & 2;
|=  Ex: a |= 2;         équivaut quasiment à         a = a | 2;
^=  Ex: a ^= 2;         équivaut quasiment à         a = a ^ 2;
<<=  Ex: a <<= 2;        équivaut quasiment à         a = a << 2;
>>=  Ex: a >>= 2;        équivaut quasiment à         a = a >> 2;
++  Ex: a++;            équivaut quasiment à         a = a + 1;
--  Ex: a--;            équivaut quasiment à         a = a - 1;

ATTENTION : l'utilisation des opérateurs ++ et -- peut vous jouer des tours en fonction que vous les utilisiez en préfixés ou en postfixés. Effectivement, si l'un de ces deux opérateur est utilisé en préfixé, il est exécuté en premier ensuite votre programme évaluera le reste de l'expression. Par contre, si vous utilisez l'opérateur en postfixé, l'incrémentation (ou la décrémentation) sera jouée à la fin du traitement de l'instruction en cours (jusqu'au ;). Le programme suivant vous présente, entre autre, cette problématique.

  
01 public class TestOperators  {
02 
03     public static void main( String [] args ) {
04 
05         // Utilisation des opérateurs += et ++
06         int [] tableau = new int[ 5 ];
07         
08         for( int i=0; i<5; i+=1 ) {
09             tableau[ i ] = i * i;
10         }
11         
12         for( int i=0; i<5; i++ ) {
13             System.out.println( tableau[ i ] );
14         }
15 
16         // Attention aux opérateurs ++ et --
17         int a = 5;
18         System.out.println( "++ en préfixé - first display " + a++ );
19         System.out.println( "++ en préfixé - second display " + a );
20         
21         a = 5;
22         System.out.println( "++ en postfixé - first display " + (++a) );
23         System.out.println( "++ en postfixé - second display " + a );
24         
25     }
26     
27 }

Les opérateurs travaillant sur les chaînes de caractères

Deux opérateurs déjà présentés dans ce document peuvent aussi être utilisé avec des chaînes de caractères ; il s'agit des opérateurs + et +=. Dans ce cas ils n'effectueront pas d'additions, mais bien des concaténations de chaînes de caractères. Ces possibilités ont déjà largement étaient utilisés dans les exemples précédents.

Les autres opérateurs Java

Le tableau suivant présente quelques autres opérateurs du langage Java. Hormis le dernier, ils sont tous repris du langage C++ : leurs fonctionnements restent similaires. A la suite de ce tableau vous trouverez un petit exemple d'utilisation de certains de ces opérateurs.

Opérateur Explications complémentaires
new Cet opérateur permet d'allouer dans le tas (le heap, en anglais) un bloc de mémoire : il retourne une référence (un pointeur) sur le bloc de mémoire alloué. Nous avons déjà tester cet opérateur lors de l'allocation d'un tableau (int [] tb = new int[10];). Si vous êtes développeur C++, notez que son homologue delete n'existe pas en Java (le Garbage Collector de la JVM étant chargé de libérer les ressources).
[] Cet opérateur permet notamment d'accéder aux éléments d'un tableau.
. Opérateur de travers : il est utilisé pour accéder aux champs (attributs et méthodes) des objets. Par exemple : "string".toUpperCase().
? : Opérateur conditionnel (c'est le seul opérateur acceptant trois opérandes en Java). Il permet de renvoyer une expression ou un autre en fonction du résultat d'une troisième expression. Sa syntaxe est la suivante : expTest ? expThen : expElse.
instanceof Permet de tester si un objet est compatible avec un type de données particulier. Cet opérateur tient compte du polymorphisme (nous y reviendrons ultérieurement).

  
01 public class TestOperators  {
02 
03     public static int min( int a, int b ) {
04         return a <= b ? a : b;
05     }
06     
07     public static void main( String [] args ) {
08 
09         // Test de l'opérateur conditionnel
10         System.out.println( "min(3, 4) == " + min( 3, 4 ) );
11         
12         // Test de l'opérateur instanceof
13         Object ptr = args;        // Par polymorphisme (on verra plus tard)
14         System.out.println( ptr instanceof String );
15         
16         ptr = "toto";
17         System.out.println( ptr instanceof String );
18         
19     }
20     
21 }

La table de précédence des opérateurs Java


La table de précédence des opérateurs Java

Comme vous l'avez certainement déjà remarqué, il est possible de se servir de parenthèses pour fixer l'ordre d'évaluation des sous-expressions formant une expression Java. Ainsi, les expressions 3*2+4 et 3*(2+4) n'auront pas les mêmes valeurs (10 et 18). Mais attention tout de même : l'utilisation abusive des parenthèses rend très rapidement un code illisible. Dans le but de ne pas arriver dans de telles situations, sachez que des règles de priorités ont étaient définies sur les opérateurs. Le tableau suivant fixe cet ordre : des plus prioritaires (en haut) aux moins prioritaires (en bas).

Liste des opérateurs des plus prioritaires (en haut) au moins prioritaires (en bas)
[ ] .
! ++ --
* / %
+ -
<< >>
== != < <= > >=
&
^
|
&&
||
?:
= += -= *= /= %= <<= >>= &= ^= |=


Les types de données Les instructions