Participer au site avec un Tip
Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Synthèse sur les opérateurs Java

Les classes enveloppantes Définition de blocs d'instructions



Accès rapide :
Les opérateurs de transtypage (cast operators)
Les opérateurs arithmétiques
Les opérateurs de manipulation de la représentation binaire de vos nombres
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 met en jeu 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 explicite 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 reconnaît 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 utilisables 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 met 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 de manipulation de la représentation binaire de vos nombres

Ils permettent de manipuler la représentation binaire de vos nombres entiers. Les opérateurs binaires sont : &, |, ^, ~, <<, >> et >><. Notez aussi les variantes combinées à des affectations : &=, |=, ^=, <<=, >>= et >><=.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
public class Demo {

    public static void main( String [] args ) {
    
        int value1 = 0b10101010;
        int value2 = 0b00001111;
        
        // & (AND)   | (OR)    ^ (XOR)    ~ (NOT)
        System.out.println( "NOT - " + Integer.toBinaryString( ~value1 ) );
        System.out.println( "AND - " + Integer.toBinaryString( value1 & value2 ) );
        System.out.println( "OR  - " + Integer.toBinaryString( value1 | value2 ) );
        System.out.println( "XOR - " + Integer.toBinaryString( value1 ^ value2 ) );   

        int value = 0b00010001;
           
        // << (signed left shift)    >> (signed right shift)     >>> (unsinged right shift)
        System.out.println( "2 x <<  - " + Integer.toBinaryString( value ) 
                          + " -> " + Integer.toBinaryString( value << 2 )
                          + " [" + value + " -> " + (value << 2) + "]");
        System.out.println( "2 x >>  - " + Integer.toBinaryString( value )
                          + " -> " + Integer.toBinaryString( value >> 2 ) 
                          + " [" + value + " -> " + (value >> 2) + "]");
                          
        System.out.println( "2 x >>>  - " + Integer.toBinaryString( -1 )
                          + " -> " + Integer.toBinaryString( -1 >>> 2 ) 
                          + " [-1 -> " + (-1 >>> 2) + "]");
    }
    
}
Exemple d'utilisation des quelques opérateurs de manipulation de la représentation binaires de vos nombres

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 affectations 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 >>>= 2;        équivaut quasiment à         a = a >>> 2;
++  Ex: a++;            équivaut quasiment à         a = a + 1;
--  Ex: a--;            équivaut quasiment à         a = a - 1;
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érateurs 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 été utilisées 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à testé 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)
Priorité Operateurs Description Associativité
Les plus prioritaires
()
[]
.
Opérateur parenthèse
Accès à une entrée d'un tableau
Sélection d'un membre
De la gauche vers la droite
 
expr++
expr--
Incrémentation postfixe
Décrémentation postfixe
De la droite vers la gauche
 
++expr
--expr
+
-
!
~
(type)
Incrémentation préfixe
Décrementation préfixe
Opérateur unaire de signe positif
Opérateur unaire de signe négatif
Négation logique
Complément binaire (not)
Opérateur de transtypage (cast)
De la droite vers la gauche
 
*
/
%
Multiplication
Division
Modulo (reste de la division entière)
De la gauche vers la droite
 
+
-
Addition
Soustraction
De la gauche vers la droite
 
<<
>>
>>>
Décalage de bits vers la gauche
Décalage de bits vers la droite
Décalage de bits vers la droite (non signé)
De la gauche vers la droite
 
<
<=
>
>=
instanceof
Infériorité stricte
Infériorité
Supériorité stricte
Supériorité
Vérification du typage
De la gauche vers la droite
 
==
!=
Egalité
Différence
De la gauche vers la droite
  & « ET » en représentation binaire De la gauche vers la droite
  ^ « OU exclusif » (XOR) en représentation binaire De la gauche vers la droite
  | « OU » en représentation binaire De la gauche vers la droite
  && « ET » logique De la gauche vers la droite
  || « OU » logique De la gauche vers la droite
  ?: L'opérateur conditionnel De la droite vers la gauche
Les moins prioritaires = += -= *= /= %= <<= >>= >>>= &= ^= |= Affectations combinées De la droite vers la gauche


Les classes enveloppantes Définition de blocs d'instructions