Programmation Orientée Objet avec Java

cours 6 : Expressions et Opérateurs

 

Expressions en Java

Définition :

Les expressions sont des entités composées de littéraux, de variables, d'invocations de méthodes et d'opérateurs.

4 + a / f(x) // Exemple d'expression complexe

Expressions primaires :

  • Littéraux ou variables simples
  • La valeur résultante est la valeur littérale ou la valeur de la variable
  • Le type résultant est celui de la valeur littérale ou de la variable
141 // Littéral entier (type int, valeur 141)
true // Littéral booléen (type boolean, valeur true)
total // Variable (type selon déclaration, valeur actuelle)

Expressions complexes :

Composées d'expressions primaires (opérandes) et d'opérateurs.

total = 141 // Expression d'affectation
1 + 2 // Expression avec opérateur d'addition
total = 7 + b // Addition et affectation
r = p.min(a, b) // Avec invocation de méthode

Quiz 1 : Expressions primaires

Parmi les éléments suivants, lesquels sont des expressions primaires valides en Java?

  • 123
  • age
  • 2 + 3
  • true
  • calculerTotal()

Réponse :

  • 123 : ✓ Expression primaire (littéral)
  • age : ✓ Expression primaire (variable)
  • 2 + 3 : ✗ Expression complexe (opérateur +)
  • true : ✓ Expression primaire (littéral booléen)
  • calculerTotal() : ✗ Expression complexe (invocation de méthode)

Opérateurs en Java

Classification par nombre d'opérandes :

  • Opérateurs unaires (monadiques) : 1 opérande
    -b // Opérateur monadique moins
    a++ // Post-incrémentation
  • Opérateurs binaires (dyadiques) : 2 opérandes
    a * b // Multiplication
    y = z // Affectation
    (int)y // Transtypage
  • Opérateurs ternaires : 3 opérandes
    x > y ? x : y // Retourne la valeur maximale

Liste des Opérateurs par Précédence

Opérateurs de haute précédence (15-12) :

Préc. Assoc. Opérateur Type des opérandes Opération
15 G . [] (params) objet, membre
tableau, int
méthode, params
Accès au membre
Accès au tableau
Invocation de méthode
14 D ++ -- variable Post-incrémentation/décrémentation
14 D ++ -- + - ~ ! variable
nombre
entier
booléen
Pré-incrémentation/décrémentation
Plus/moins monadique
Complément binaire
NON logique
13 D new (type) classe, params
type, quelconque
Création d'objet
Transtypage
12 G * / % nombre, nombre Multiplication, division, modulo

Opérateurs de moyenne précédence (11-8) :

Préc. Assoc. Opérateur Type des opérandes Opération
11 G + - nombre, nombre Addition, soustraction
11 G + chaîne, quelconque Concaténation
10 G << >> >>> entier, entier Décalage à gauche, droite, non-signé
9 G < <= > >= instanceof nombre, nombre
nombre, nombre
référence, type
Comparaisons
Comparaisons
Comparaison de types
8 G == != primitif, primitif
référence, référence
Égalité/non-égalité de valeurs
Égalité/non-égalité de références

Opérateurs de basse précédence (7-1) :

Préc. Assoc. Opérateur Type des opérandes Opération
7 G & entier, entier
booléen, booléen
ET binaire (bit à bit)
ET logique
6 G ^ entier, entier
booléen, booléen
OU exclusif binaire
OU exclusif logique
5 G | entier, entier
booléen, booléen
OU binaire
OU logique
4 G && booléen, booléen ET logique conditionnel
3 G || booléen, booléen OU logique conditionnel
2 D ? : booléen, quelconque, quelconque Opérateur conditionnel (ternaire)
1 D = += -= *= /= %= etc. variable, quelconque Affectation
Affectation avec opération

Quiz 2 : Précédence des opérateurs

Quelle sera la valeur de resultat après l'exécution de ce code?

int a = 5, b = 3, c = 2;
int resultat = a + b * c;

Réponse : resultat = 11

Explication : La multiplication (*) a une précédence (12) plus élevée que l'addition (+, précédence 11). Donc :

a + b * c = 5 + (3 * 2) = 5 + 6 = 11

Précédence et Associativité

Précédence :

  • Définit quelles opérandes sont liées à quels opérateurs en l'absence de parenthèses
  • Plus le degré de précédence est élevé, plus les opérandes sont liées à l'opérateur
  • Les parenthèses permettent de spécifier explicitement les liens

Associativité :

  • Gauche (G) : Les opérations sont exécutées de gauche à droite
  • Droite (D) : Les opérations sont exécutées de droite à gauche
// Exemple avec parenthèses explicites
1 + 3 * 4 - 2 - 5
// Équivalent à :
((1 + (3 * 4)) - 2) - 5
Conseil : Sauf cas triviaux, toujours mettre des parenthèses dans les expressions complexes pour éviter toute ambiguïté.

Opérateurs Arithmétiques

-2.7 // Moins monadique
i++ // Post-incrémentation
--j - 2 // Pré-décrémentation et soustraction
a * x*x + 4.2 // Multiplication et addition
5.6 / 3 // Division
17 % 5 // Modulo (reste de division) - différent de 17/5

Quiz 3 : Opérateurs arithmétiques

Quelles sont les valeurs des variables après ces opérations?

int a = 10;
int b = a++;
int c = ++a;

Réponse :

  • a = 12
  • b = 10
  • c = 12

Explication :

  • a++ : post-incrémentation - utilise la valeur actuelle (10) puis incrémente
  • ++a : pré-incrémentation - incrémente d'abord (11→12) puis utilise la valeur

Ordre d'Évaluation

Règles importantes :

  • L'ordre d'évaluation des opérandes se fait de gauche à droite
  • L'ordre des opérations dépend de la précédence et de l'associativité
  • Les expressions complexes doivent être écrites de manière non ambiguë
// Exemple à éviter - expression ambiguë
int i = 10;
i = i + (i=5); // Résultat imprévisible

// Meilleure écriture
int j = 5;
i = 10 + j;

Évaluation des Opérations

Règles de conversion automatique :

  • Si un opérande est flottant → arithmétique décimale
  • Si les deux opérandes sont entiers → arithmétique entière
  • Les caractères (char) sont traités comme des entiers
byte b = 12;
short s = 167;
int i = s - b; // s et b convertis en int avant opération

float f = 1.2f;
double d = f * 2.5; // f converti en double avant opération

Schéma d'évaluation des expressions arithmétiques :

// Exemple : 17 / 3 + 1.0
// Étape 1 : 17 / 3 = 5 (division entière)
// Étape 2 : 5 + 1.0 = 6.0 (conversion int → double)

Quiz 4 : Évaluation d'expressions

Quel est le résultat de cette expression?

double resultat = 10 / 4;

Réponse : resultat = 2.0

Explication : La division 10 / 4 est une division entière qui donne 2, puis ce résultat est converti en double pour l'affectation.

Pour obtenir 2.5, il faudrait écrire : 10.0 / 4 ou 10 / 4.0

Opérateurs Relationnels

i < 5 // Plus petit
if (age >= 18) {...} // Plus grand ou égal
while (i < 100) {...} // Plus petit
if (objet1 != objet2) {...} // Comparaison de références
Attention : Pour les types référence, == et != comparent les références (adresses mémoire), pas le contenu des objets.

Opérateurs et Nombres Flottants

Problème important : Les nombres flottants sont des approximations. Il faut être très prudent avec les comparaisons.
float a = 1.0f, b = 0.1f, c = 0.2f;
(a + (b + c)) != ((a + b) + c) // Peut être true !
float d = 2.0E7f;
d == (d + 1) // Peut être true !
Solution : Pour comparer des flottants, utiliser une tolérance :
Math.abs(x - y) < 0.0001 // Au lieu de x == y

Opérateurs Logiques

if (!found) {...} // NON logique
if (size > 1.4 || age > 12) {...} // OU conditionnel
if (t != null && t.length >= 2 && t[1] != 4) {...} // ET conditionnel

Différence entre &/| et &&/|| :

// ET logique simple - évalue toujours les deux opérandes
if (a & b) {...}

// ET logique conditionnel - n'évalue le 2ème que si nécessaire
if (a && b) {...} // Si a est false, b n'est pas évalué

Quiz 5 : Opérateurs logiques conditionnels

Que se passe-t-il dans ce code?

int x = 5;
int y = 0;
if (x != 0 && y / x > 2) {
    System.out.println("Condition vraie");
}

Réponse : Aucune erreur, le message n'est pas affiché.

Explication : Comme x != 0 est vrai, le deuxième opérande y / x > 2 est évalué. y / x vaut 0, donc 0 > 2 est faux. L'opérateur && nécessite que les deux opérandes soient vrais.

Attention : Si on utilisait & au lieu de &&, les deux opérandes seraient toujours évalués, mais le résultat serait le même.

Opérateurs Orientés Bits

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)

Affectation et Opérateurs Combinés

Affectation simple :

a = b + c; // La variable a prend pour valeur (b + c)
a = b = c; // Associativité à droite : a = (b = c)

Affectation avec opérateur :

i += 2; // Équivaut à i = i + 2;
a *= z + 4; // Équivaut à a = a * (z + 4);
flag |= mask; // Active des bits selon un masque

Quiz 6 : Opérateurs d'affectation

Quelle est la valeur de x après ces opérations?

int x = 10;
x += 5;
x *= 2;
x -= 8;

Réponse : x = 22

Calcul :

  • x = 10 (initialisation)
  • x += 5x = 10 + 5 = 15
  • x *= 2x = 15 * 2 = 30
  • x -= 8x = 30 - 8 = 22

Opérateur instanceof

 

L'opérateur instanceof en Java

L'opérateur instanceof en Java est utilisé pour tester si un objet est une instance d'une classe, d'une interface, d'une sous-classe ou implémente une interface donnée.

Syntaxe

objet instanceof Type
  • Retourne true si objet est du type Type (ou d'un sous-type).
  • Retourne false sinon.

Exemples

String str = "Bonjour";
System.out.println(str instanceof String); // true

Object obj = str;
System.out.println(obj instanceof String);  // true
System.out.println(obj instanceof Object);  // true

Integer num = 42;
System.out.println(num instanceof Number);  // true (Integer étend Number)
System.out.println(num instanceof String);  // false

Cas particuliers

1. Avec null

String s = null;
System.out.println(s instanceof String); // false

2. Hiérarchie de classes

class Animal {}
class Chien extends Animal {}

Animal animal = new Chien();
System.out.println(animal instanceof Chien);  // true
System.out.println(animal instanceof Animal); // true

3. Interfaces

class MaClasse implements Runnable {}
MaClasse mc = new MaClasse();
System.out.println(mc instanceof Runnable); // true

Depuis Java 14 : instanceof avec pattern matching

Nouveauté Java 14+ : Le pattern matching permet de combiner test et cast en une seule ligne.

 

if (obj instanceof String s) {
    System.out.println(s.length()); // s est directement utilisable
}

Évite le cast manuel :

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.length());
}

Récapitulatif du rôle

Fonction Description
Vérification de type Teste l'appartenance à une classe/interface
Sécurité avant cast Évite ClassCastException
Pattern matching (Java 14+) Simplifie le code avec cast automatique

En résumé : instanceof permet de vérifier dynamiquement le type d’un objet au runtime, essentiel pour le polymorphisme et la programmation sûre en Java.

"Texte" instanceof String; // true
"Texte" instanceof Object; // true
null instanceof String; // false

// Utile pour prévenir des erreurs de transtypage
if (forme instanceof Polygone) {
    Polygone p1 = (Polygone)forme;
}

Opérateurs Particuliers

// Accès à un membre d'objet
obj.x
obj.f()

// Accès à un élément de tableau
t[2]

// Invocation de méthode
rectangle.move(x, y)

// Création d'objet
new Point(4.0, -2.5);
new ArrayList();

// Transtypage
(float)position
(int)(a * 1.414f)

Quiz 7 : Opérateur conditionnel ternaire

Quelle est la valeur de max après cette opération?

int x = 10, y = 15;
int max = (x > y) ? x : y;

Réponse : max = 15

Explication : L'opérateur ternaire condition ? valeur1 : valeur2 évalue la condition :

  • Si condition est vraie → retourne valeur1
  • Si condition est fausse → retourne valeur2

Ici, x > y (10 > 15) est faux, donc max prend la valeur y (15).

Exercice de Synthèse

Exercice Final : Évaluation d'expression complexe

En utilisant les règles de précédence et d'associativité, évaluez cette expression pas à pas :

int a = 5, b = 3, c = 2;
boolean resultat = a > b && c != 0 || a + b == c * 4;

Correction détaillée :

  1. a > b5 > 3true
  2. c != 02 != 0true
  3. a + b5 + 38
  4. c * 42 * 48
  5. a + b == c * 48 == 8true
  6. a > b && c != 0true && truetrue
  7. true || truetrue

Résultat final : resultat = true

Ordre des opérations avec parenthèses :

((a > b) && (c != 0)) || ((a + b) == (c * 4))

Résumé du Chapitre

  • Les expressions combinent littéraux, variables et opérateurs pour produire une valeur
  • Les opérateurs sont classés par nombre d'opérandes (unaire, binaire, ternaire)
  • La précédence détermine l'ordre d'évaluation des opérations
  • L'associativité détermine l'ordre gauche-droite ou droite-gauche
  • Les opérateurs arithmétiques effectuent des calculs numériques
  • Les opérateurs relationnels comparent des valeurs
  • Les opérateurs logiques combinent des conditions booléennes
  • Les opérateurs d'affectation assignent des valeurs aux variables
  • L'opérateur instanceof teste la compatibilité des types
 
Aucune note. Soyez le premier à attribuer une note !

Ajouter un commentaire

Anti-spam