Informatique / Programmation Programmation orientée objet avec Java 02 : Expressions et opérateurs Jacques Bapst jacques.bapst@hefr.ch
Expressions [1] Les expressions sont des entités composées de littéraux, de variables, d'invocations de méthodes et d'opérateurs. Ex : 4 + a / f(x) Les expressions sont des éléments syntaxiques permettant de déterminer une valeur à partir d'autres valeurs L'évaluation d'une expression détermine une valeur et un type de retour Les expressions primaires : littéraux ou variables La valeur résultante de l'évaluation d'une expression primaire est la valeur littérale ou la valeur enregistrée dans la variable. Le type résultant est celui de la valeur littérale ou de la variable Exemples : 141 Littéral entier (type int, valeur 141) true total Littéral booléen (type boolean, valeur true) Variable (type selon déclaration de variable, valeur actuelle de total) EIA-FR / Jacques Bapst PR1_02 2
Expressions [2] Les expressions complexes sont composées d'expressions primaires (opérandes) et d'opérateurs (y c. invocation de méthodes) Exemples : total = 141 Expression d'affectation 1 + 2 Expression avec opérateur d'addition total = 7 + b r = p.min(a, b) Expression comprenant une addition et une affectation Expression comprenant une invocation de méthode La valeur et le type d'une expression complexe sont déterminés par les valeurs et types des opérandes ainsi que par les opérateurs qui interviennent dans l'expression (les règles seront vues plus tard). Certains opérateurs ont des effets de bord : ils changent par ex. la valeur des opérandes et donc modifient l'état du programme (affectation, incrémentation, décrémentation, invocation de méthodes, création d'objets) a = 2 i++ EIA-FR / Jacques Bapst PR1_02 3
Opérateurs Les opérateurs sont des éléments syntaxiques qui effectuent certaines opérations en utilisant les valeurs de leurs opérandes (paramètres de l'opération). Opérateurs unaires (monadiques) -b Opérateur monadique moins a++ Opérateurs binaires (dyadiques) a * b y = z (int)y Opérateurs ternaires 1 opérande Opérateur monadique de post-incrémentation 2 opérandes L'opérateur de multiplication est binaire L'affectation est également binaire Transtypage (casting) Un seul opérateur ternaire en Java x > y? x : y Opérandes 3 opérandes Retourne la valeur maximale entre x et y Op Résultat EIA-FR / Jacques Bapst PR1_02 4
Liste des opérateurs [1] P A Opérateur Type(s) des opérandes Opération 15 G. [] ( params ) ++, -- objet, membre tableau, int méthode, liste de paramètres variable accès au membre d'un objet accès à l'élément d'un tableau invocation (appel) de méthode post-incrémentation, décrémentation 14 D ++, -- +, - ~! 13 D new ( type ) variable nombre entier booléen classe, liste de paramètres type, quelconque pré-incrémentation, décrémentation plus monadique, moins monadique complément binaire NON logique création (instanciation) d'objet transtypage (conversion de type) 12 G *, /, % nombre, nombre multiplication, division, modulo 11 G +, - + nombre, nombre chaîne de caract., quelconque addition, soustraction concaténation 10 G <<, >>, >>> entier, entier décalage à gauche, droite, non-signé 9 G <, <= >, >= instanceof 8 G ==!= ==!= P : Précédence A : Associativité nombre, nombre nombre, nombre référence, type primitif, primitif primitif, primitif référence, référence référence, référence inférieur, inférieur ou égal supérieur, supérieur ou égal comparaision de types égalité (valeurs égales) non-égalité égalité (référence au même objet) non-égalité EIA-FR / Jacques Bapst PR1_02 5
Liste des opérateurs [2] P A Opérateur Type(s) des opérandes Opération 7 G & entier, entier ET binaire (bit à bit) & booléen, booléen ET logique 6 G ^ ^ 5 G entier, entier booléen, booléen entier, entier booléen, booléen OU exclusif binaire (bit à bit) OU exclusif logique OU binaire (bit à bit) OU logique 4 G && booléen, booléen ET logique conditionnel 1) 3 G booléen, booléen OU logique conditionnel 1) 2 D? : booléen, quelconque, quelconque opérateur conditionnel (ternaire) 1 D = *=, /=, %=, +=, -=, <<=, >>=, >>>=, &=, ^=, = P : Précédence A : Associativité variable, quelconque variable, quelconque affectation affectation avec opération 1) L'opérande de droite n'est évaluée que si c'est nécessaire EIA-FR / Jacques Bapst PR1_02 6
Précédence et Associativité Précédence (voir colonne P dans la liste des opérateurs) Définit, en l'absence de parenthèses, quelles opérandes sont liés à quels opérateurs Plus le degré de précédence est élevé et plus les opérandes sont liés à l'opérateur considéré Les parenthèses permettent de spécifier explicitement les liens entre les opérandes et les opérateurs Conseil : Sauf cas triviaux, toujours mettre des parenthèses dans les expressions complexes afin d'éviter toute ambiguïté d'interprétation Associativité (voir colonne A dans la liste des opérateurs) S'il y a plusieurs opérateurs de même précédence, l'associativité définit l'ordre dans lequel les opérations seront exécutées De la gauche vers la droite (G) De la droite vers la gauche (D) EIA-FR / Jacques Bapst PR1_02 7
Opérateurs arithmétiques Effectuent des opérations arithmétiques et retournent des résultats numériques Le type du résultat dépend du type des opérandes Si nécessaire, une conversion élargissante (automatique) des opérandes est effectuée avant l'opération + - plus, moins monadique + - addition, soustraction ++ -- pré/post incrémentation, pré/post décrémentation * / % multiplication, division, modulo (reste de la division entière) -2.7 i++ --j - 2 a * x*x + 4.2 5.6/3 17 % 5 ( ne pas confondre avec 17 / 5 ) EIA-FR / Jacques Bapst PR1_02 8
Ordre d'évaluation Pour mettre en évidence l'ordre d'évaluation des opérations d'une expression, on peut placer des parenthèses en fonction de la précédence et de l'associativité des opérateurs impliqués : Précédence 1 + 3 * 4-2 - 5 11 12 11 11 G G G G ( ( 1 + ( 3 * 4 ) ) - 2 ) - 5 Associativité v = a - i++ 1 11 14 D G D v = ( a - ( i++ ) ) Après placement des parenthèses, les opérateurs ne devraient avoir comme opérandes que des expressions entre parenthèses ou éventuellement un symbole ou une valeur littérale unique (isolé). Analyse non terminée : u = (a * b) - (c * d) + f(e); EIA-FR / Jacques Bapst PR1_02 9
C o m p l é m e n t Java / Expressions et opérateurs Ordre d'évaluation / Ordre des opérations Dans des expressions plus complexes (et un peu tordues) il est nécessaire de bien distinguer l'ordre d'évaluation des opérandes (qui s'effectue de gauche à droite) et l'ordre des opérations (qui dépend de la précédence et de l'associativité des opérateurs). De telles expressions pièges sont à éviter (il faut impérativement écrire le code de manière moins ambiguë). int i = 10; i = i + (i=5); int i=2; i = ++i + ++i * ++i; int i=1, j=2; i = i+++j; EIA-FR / Jacques Bapst PR1_02 10
Évaluation des opérations [1] Si l'un des opérandes est un nombre en virgule flottante, l'arithmétique décimale (arithmétique réelle) est utilisée (calcul en virgule flottante) Si les deux opérandes sont des nombres entiers, l'arithmétique entière est utilisée (important pour les divisions et pour le domaine des valeurs possibles) Les caractères (char) sont traités comme des entiers short (leur valeur Unicode est utilisée) L'arithmétique entière est circulaire et ne produit jamais de dépassement (une division par zéro lève cependant l'exception ArithmeticException) L'arithmétique décimale (en virgule flottante) peut produire des valeurs spéciales (infini, -infini, zéro négatif, NaN) mais ne lève jamais d'exceptions EIA-FR / Jacques Bapst PR1_02 11
Évaluation des opérations [2] Le résultat d'une expression entière est de type int 1) sauf si l'un des opérandes est de type long, auquel cas l'expression est de type long (voir diagramme page suivante) Le résultat d'une expression réelle (comprenant au moins un opérande en virgule flottante) est de type float 1) sauf si l'un des opérandes est de type double, auquel cas l'expression est de type double (voir diagramme page suivante) 1) par conversion élargissante automatique (promotion) des opérandes byte b = 12; short s = 167; float f = 1.2f; int i = s - b; // Expression entière, s et b sont convertis en int // avant l'opération double d = f * 2.5; // Expression réelle, f est converti en double avant // l'opération (car 2.5 est de type double) EIA-FR / Jacques Bapst PR1_02 12
Évaluation des expressions arithmétiques Pour chaque opérateur arithmétique, d'éventuelles conversions préalables sont effectuées en fonction du type de ses opérandes : N Nb à virg.? Y N long? Y N double? Y Conversion év. et calcul en int Conversion év. et calcul en long Conversion év. et calcul en float Conversion év. et calcul en double Arithmétique entière Arithmétique décimale Exemple : 17 / 3 + 1.0 EIA-FR / Jacques Bapst PR1_02 13
==!= égalité, inégalité < > plus petit, plus grand Opérateurs relationnels Effectuent des opérations de comparaison et retournent des résultats booléens <= >= plus petit ou égal, plus grand ou égal i < 5 if (age >= 18) {...} while (i<100) {...} if (objet1!= objet2) {...} // Comparaison des références Attention : pour les types références (objets et tableaux) les opérateurs d'égalité et d'inégalité comparent les références et non les valeurs référencées. EIA-FR / Jacques Bapst PR1_02 14
Opérateurs et nombres en virgule flottante Les nombres en virgule flottante (float et double) ne sont que des approximations des nombres réels car ils sont codifiés (en base 2) avec un nombre limité de bits pour la mantisse et pour l'exposant (voir par ex. www.binaryconvert.com ou babbage.cs.qc.edu/ieee-754). Même à l'intérieur du domaine de valeurs prévu et avec un nombre de décimales inférieur à la précision maximale, une grande quantité de nombres réels ne peuvent pas être représentés exactement. C'est pourquoi il faut être très prudent lors de l'utilisation des opérateurs relationnels avec les nombres en virgule flottante et tenir compte de ces problèmes d'arrondi. float a=1.0f, b=0.1f, c=0.2f; (a+(b+c))!= ((a+b)+c) //!!! true!!! (a+(b+c)) < ((a+b)+c) //!!! true!!! float d=2.0e7f; d == (d+1) //!!! true!!! EIA-FR / Jacques Bapst PR1_02 15
Opérateurs logiques Effectuent des opérations logiques et retournent des résultats booléens! NON logique & && ET logique OU logique ET logique conditionnel (le 2 ème opérande n'est évalué que si le 1 er est vrai) OU logique conditionnel (le 2 ème opérande n'est évalué que si le 1 er est faux) ^ OU exclusif logique Ne pas confondre avec l'élévation à la puissance! if (!found) {...} if (size>1.4 age>12) {...} if (t!=null && t.length>=2 && t[1]!=4) {...} EIA-FR / Jacques Bapst PR1_02 16
Opérateurs orientés bits Effectuent des opérations bit à bit et retournent des résultats entiers (signés) ~ Inversion (complément à 1) & ET (bit à bit) OU (bit à bit) ^ OU exclusif (bit à bit) Ne pas confondre avec l'élévation à la puissance! << Décalage à gauche (zéros ajoutés à droite) >> Décalage à droite signé (bit du signe ajouté à gauche) >>> Décalage à droite non-signé (zéros ajoutés à gauche) byte b = ~12 // ~00001100 => 11110011 (-13) 10 & 7 // 00001010 & 00000111 => 00000010 ( 2) 10 7 // 00001010 00000111 => 00001111 ( 15) 10 ^ 7 // 00001010 ^ 00000111 => 00001101 ( 13) 10 << 2 // 00001010 => 00101000 ( 40) 10 >> 2 // 00001010 => 00000010 ( 2) -10 >> 2 // 11110110 => 11111101 ( -3) -10 >>>2 // 11110110 => 00111101 ( 61) EIA-FR / Jacques Bapst PR1_02 17
Affectation / Assignation Enregistre dans l'opérande de gauche (variable) la valeur de l'opérande de droite (valeur de l'expression) Le type de la variable (opérande de gauche) doit être compatible avec le type de l'expression de droite (si nécessaire, conversion élargissante automatique) Le type et valeur de retour d'une expression d'affectation correspondent au type de la variable et, respectivement, à sa valeur après affectation Attention : Ne pas confondre l'opérateur d'affectation (=) avec celui d'égalité (==) "prend pour valeur" et non pas "est égal à" a = b + c; // La variable a prend pour valeur le résultat de la somme (b+c) a = b = c; // Associativité à droite a = (b = c) t[i] = circle.center(); EIA-FR / Jacques Bapst PR1_02 18
Affectation avec opérateur Combinaison de l'affectation avec un opérateur (arithmétique ou orienté bits) Le type de l'opérande de gauche (variable) doit être compatible avec le type de l'expression de droite var op= expr est équivalent à var = var op ( expr ) Opérateurs combinés : += -= *= /= %= &= = ^= <<= >>= >>>= i += 2; // i = i + 2; a *= z + 4; // a = a * (z + 4); flag = mask; // flag = flag mask; // set some bits according to a mask EIA-FR / Jacques Bapst PR1_02 19
Sera vu plus en détail dans le cadre du polymorphisme Java / Expressions et opérateurs Opérateur instanceof Permet de tester si une expression (de type référence) est compatible (convertible) avec un type donné. Retourne true si l'opérande de gauche (qui doit être une expression de type objet ou tableau) est une instance du type spécifié par l'opérande de droite (qui doit être un type référence) "Texte" instanceof String; // true "Texte" instanceof Object; // true null instanceof String; // false new int[] {1} instanceof Object // true new int[] {1} instanceof byte[] // false tableau d'int tableau de byte // Utile pour prévenir des erreurs de transtypage if (forme instanceof Polygone) { Polygone p1 = (Polygone)forme; } EIA-FR / Jacques Bapst PR1_02 20
C o m p l é m e n t Java / Expressions et opérateurs Opérateurs particuliers Ces opérateurs particuliers sont parfois considérés comme des éléments syntaxiques, parfois comme opérateurs : Accès à un membre d'un objet (.) obj.x obj.f() Accès à un élément d'un tableau ([]) t[2] Invocation de méthode (()) rectangle.move(x, y) Création d'un objet (new) new Point(4.0, -2.5); new ArrayList(); Conversion de type / Transtypage (()) (float)position (int)(a*1.414f) (Circle)shape EIA-FR / Jacques Bapst PR1_02 21