Un programme passe la quasi totalité de son temps à évaluer des expressions pour produire des effets de bord ou pour calculer des valeurs. Une expression avec un effet de bord est une expression qui lorsqu'elle s'évalue, produit un changement de l'état du système. Par exemple, l'affectation est une expression qui a pour effet de bord la modification du contenu de l'opérande gauche. L'invocation d'une méthode est une expression qui lorsqu'elle s'évalue produit comme effet de bord, l'appel de la méthode après évaluation des paramètres de la méthode.
Le résultat de l'évaluation d'une expression est soit une valeur, soit une variable (en C, une lvalue ) soit void. Le résultat de l'évaluation d'une expression est void dans l'unique cas de l'invocation d'une méthode qui ne retourne rien (une procédure).
A priori, c'est notre culture mathématique qui nous permet de parenthéser ces expressions. Pour éviter l'usage des parenthèses qui alourdissent la lecture, et lorsque cela est possible, les mathématiciens ont fixé des règles pour que tout le monde parenthèse (dans sa tête) de la même manière toute expression ambiguë.
Par exemple, dans l'expression 2 + 3*4 , la sous expression 3*4 est évaluée en premier et le résultat obtenu est ajouté à la valeur 2 (forme parenthésée : 2 + (3*4)) . On dit que l'opérateur * possède une priorité supérieure à la priorité de l'opérateur + . De même, dans l'expression 2 - 3 - 4 , la sous expression 2 - 3 est évaluée en premier et, au résultat obtenu, on soustrait la valeur 4 (forme parenthésée : (2 - 3) - 4) . On dit que l'ordre d'évaluation de l'opérateur - est de gauche à droite.
Les opérandes de chaque opération sont complètement évalués avant d'effectuer l'opération. Il existe, cependant trois exceptions : il s'agit des opérateurs &&, || et ? :. Java garantit également que les opérandes sont évalués de gauche à droite. Par exemple, dans l'expression x + y , on est sûr que x est évalué avant y . Cette connaissance de l'ordre d'évaluation est particulièrement importantes lorsqu'il s'agit d'expressions avec des effets de bord.
Toutes les expressions, syntaxiquement correctes, ont un type . Le type des expressions sont toujours connus dès la ``compilation''. Une expression de type T peut être affectée à une variable du même type ou d'un type compatible .
Le type d'expression est donnée par le type des opérandes et de la sémantique des opérateurs. Tous types entiers autre que long sont convertis en int avant d'être évalués. Le résultat est de type int à moins que l'un des opérandes soit de type long.
L'évaluation d'une expression peut conduire à une erreur. Dans ces cas, Java lance une exception (voir 10) précisant la raison exacte de l'erreur.
L'opération la plus importante dans un langage de programmation est celle qui consiste à donner une valeur à une variable. Cette opération appelée affectation est désignée par le symbole =.
L'affectation range une valeur dans une variable (une zone mémoire), il est impératif que le membre gauche d'une affectation représente une zone mémoire : c'est ce qu'on appelle une lvalue en C . Une constante n'est pas une lvalue car il ne désigne pas l'adresse d'une zone mémoire. Elle ne peut donc pas figurer en membre gauche d'une affectation.
Le membre droit d'une affectation peut désigner soit une constante soit une zone mémoire soit une expression quelconque : l'affectation x = 2 range la valeur 2 dans la variable x, l'affectation x = y range dans la variable x le contenu de la variable y et l'affectation x = y + 1 range dans la variable x le contenu de la variable y incrémenté de 1.
L'affectation est une expression.La valeur d'une affectation est la valeur de son membre gauche après exécution de l'affectation. Si la variable y contient la valeur 100 alors l'affectation x=y+20 a pour valeur 120.
Une affectation peut figurer en membre droit d'une autre affectation.L'affectation x=y=1 est parfaitement valide car elle représente l'affectation x=(y=1). Puisque y=1 est une expression, elle peut figurer en membre droit d'une affectation. Puisque elle est syntaxiquement correcte, quel sens donner à cette affectation ? L'expression y=1 a pour valeur celle de son membre droit (ici la valeur entière 1), l'affectationx=y=1 range dans la variable x la valeur 1 après avoir rangé dans y cette même valeur 1. Ainsi, l'affectation x1=x2=x3=...=x20=0 est équivalent à la suite d'affectations (dans l'ordre indiqué) x20=0, x19=0, x18=0, ..., x1=0.
Une erreur de compilation est générée lorsque le type de l'expression membre droit de l'affectation ne peut être converti en le type du membre gauche.
A l'exécution, si l'opérande gauche n'est pas un élément d'un tableau, l'opérande gauche est tout d'abord évalué, ensuite l'opérande droit est évalué et enfin la résultat de cette dernière est convertie au type de l'opérande gauche. Si durant l'une des ces trois phases, une erreur survient, l'évaluation de l'affectation est immédiatement arrêtée et l'erreur générée pour l'affectation est cette première erreur. Si, par contre, l'opérande gauche est une élément d'un tableau, les opérations effectuées sont les suivants (dans l'ordre) :
| Précédence | Ordre | Opérateur | Type | Description |
| 13 | droite gauche | = | Variable, qcq | Affectation |
Les opérateurs +, - et * fonctionnent comme on s'y attend. Comme en C et C++ , les caractères sont un type particulier d'entier. On peut donc appliquer les opérations arithmétiques sur les caractères. Les expressions 'A' - '0', 'A' + 1 sont syntaxiquement corrects et s'évaluent parfaitement.
L'arithmétique entière de Java est une arithmétique complément à deux, modulaire. Cette arithmétique ne produit jamais de débordement car le résultat est toujours réduite modulo le domaine de valeurs du type des opérandes.
Java utilise le standard IEEE 754-1985 pour les nombres à virgules flottantes. Une opération arithmétique peut conduire soit à un underflow (valeur trop petite) ou un overflow (valeur top grande). Une opération sur les flottants peut produire un résultat pour lequel il n'existe pas une approximation permettant de le représenter par un nombre flottant. C'est, par exemple, le cas du résultat d'une division par zéro. Ce type de résultat est représenté par une valeur particulière appelée NaN (Not a Number ).
L'arithmétique flottante Java est un sous ensemble du standard IEEE-754-1985.
Tous les opérateurs multiplicatifs ont la même priorité et l'ordre d'évaluation est gauche-droite. Le type des opérandes doit être de type numérique. Le type de l'opération effectué dépend du type (après conversion) de ses opérandes. Le type d'une opération multiplicatif est soit de type entier (int ou long) soit flottant (float ou double).
Les opérations multiplicatifs sont la multiplication (*) , la division (/) et le reste de la division (%). Si l'un des opérande est NaN, le résultat est NaN.
| a | b | a x b | a/b | a%b |
| Fini | ± 0.0 |
|
|
NaN |
| Fini |
|
|
|
a |
|
|
|
|
NaN | NaN |
|
|
Fini |
|
|
NaN |
|
|
|
|
NaN | NaN |
|
|
|
NaN | NaN | NaN |
La multiplication, notée avec le symbole *, est une opération commutative sans effet de bord. Elle est associative sur les entiers et ne l'est pas sur les flottants. Lorsque le résultat de la multiplication de deux entiers dépasse des plages de valeurs permises selon le type (int ou long), le résultat est ramené au modulo du type.
| Précédence | Ordre | Opérateur | Type | Description |
| 2 | gauche droite | *, /, % | Arithmétique | Multiplication, division et reste |
Les opérations additifs, qui sont l'addition (+) et la soustraction (-), ont la même priorité et l'ordre d'évaluation est gauche-droite. Le type des opérandes doit être de type numérique. Le type de l'opération effectué dépend du type (après conversion) de ses opérandes. Le type d'une opération multiplicatif est soit de type entier (int ou long) soit flottant (float ou double).
Les opérations additifs entières, tout comme les opérations multiplicatifs, ne produit aucune erreur. Il n'y pas de débordement possible : l'arithmétique est une arithmétique e complément à 2.
Quant aux opération additifs sur les flottants, la somme de deux
infinis produit un NaN si les signes différent et l'infini sinon. La
différence de deux infinis de même signe est un NaN. ; sinon le
résultat est celui attendu.
| Précédence | Ordre | Opérateur | Type | Description |
| 3 | gauche droite | +, - | Arithmétique | Addition et soustraction |
| Précédence | Ordre | Opérateur | Type | Description |
| 1 | droite gauche | +, - | Arithmétique | Plus et moins unaire |
Il existe deux opérateurs ++ et deux opérateurs - : une pour la forme préfixée et l'autre pour la forme postfixée. Ce sont des opérateurs unaires qui s'appliquent sur un opérande de type numérique.
La valeur d'une expression de post-incrément (post décrément) est la valeur de l'opérande et a pour effet de bord, le stockage de la valeur de l'opérande incrémenté (resp. décrémenté) de 1.
La valeur d'une expression de pré-incrément (pré-décrément) est la
valeur de l'opérande incrémenté (resp. décrémenté) de 1 et a pour
effet de bord, le stockage de cette valeur.
| Précédence | Ordre | Opérateur | Type | Description |
| 1 | droite gauche | ++, - | Arithmétique | Incrémént et décrément |
Le résultat d'une compraison est une valeur boolénne (vrai ou faux).
Dans le langage Java, le résultat d'une comparaison est true
ou false selon que cette comparaison est vraie ou fausse.
| Précédence | Ordre | Opérateur | Type | Description |
| 5 | gauche droite | <,<=, >, >= | Arithmétique | Comparaison arithmétique |
| 6 | gauche droite | ==, != | objet et type primitif | egalité et différent |
produit la sortie
x = 2 ; y = 3 ; System.out.println("Le produit de " + x + " et de " + y + " est : " + x*y) ;
Le produit de 2 et de 3 est : 6
| Précédence | Ordre | Opérateur | Type | Description |
| 3 | gauche droite | + | Chaînes de caractères | Concaténation de chaînes |
On dispose des connecteurs logiques (sous une syntaxe particulière) et on peut fabriquer des expressions avec celles-ci. La valeur d'une expression booléenne est, comme le résultat des comparaisons, une valeur booléenne.
Comme d'habitude, l'évaluation d'une expression booléenne obéit aux règles de priorité et à l'ordre d'évaluation. Java propose deux types d'opérateurs logiques : les opérateurs classiques et les opérateurs conditionnels.
L'évaluation des opérations classiques se fait par l'évaluation complète de chaque opérande et l'application de l'opération sur les résultats obtenus.
L'évaluation des opérateurs conditionnels se fait par évaluation successives des opérandes. Cette évaluation s'arrête dès que l'on est capable de donner la valeur de l'expression. Par exemple, en supposant que la variable x contient la valeur 5, l'évaluation de l'expression (x >= 2) || ( x >= y) s'arrête avant même d'avoir évalué l'expression x >= y, puisque (x >= 2) est vrai d'où on peut conclure que la valeur de l'expression (x >= 2) || ( x >= y) est également vraie.
Cette remarque a son importance dans deux cas :
| Précédence | Ordre | Opérateur | Type | Description |
| 1 | droite gauche | ! | Booléen | non booléen |
| 7 | gauche droite | & | Booléen | ET booléen |
| 8 | gauche droite | ^ |
Booléen | OU exclusif booléen |
| 9 | gauche droite | | | Booléen | OU booléen |
| 11 | gauche droite | && | Booléen | ET conditionnel booléen |
| 11 | gauche droite | || | Booléen | OU conditionnel booléen |
On dispose des opérateurs suivants :
^ (OU Exclusif bit à bit)
| Précédence | Ordre | Opérateur | Type | Description |
| 1 | droite gauche | ~ |
Entier | complément bit à bit |
| 7 | gauche droite | & | Entier | ET bit à bit |
| 8 | gauche droite | ^ |
Entier | OU exclusif bit à bit |
| 9 | gauche droite | | | Entier | Ou bit à bit |
L'opérateur << décale les bits vers la gauche en complétant par des bits à zéro sur la partie droite. L'opérateur >>> décale les bits vers la droite en complétant par des bits à zéro sur la partie gauche. L'opérateur >> décale les bits vers la droite en complétant par des bits à la valeur du bit de poids fort sur la partie gauche.
Précédence Ordre Opérateur Type Description
| Précédence | Ordre | Opérateur | Type | Description |
| 4 | gauche droite | <<, >>, >>> | Entier | Décalage de bits |
Les opérateurs suivants ne sont que des raccourcis de notation : les
expressions y += x, y -= x, y *= x,
y /= x, y %= x, y >>= x, y <<= x,
y >>>= x, y &= x, y ^= x et y |= x,
correspondent aux raccourcis pour y = y+x, y = y-x,
y = y*x, y = y/x, y = y%x, y =
y>>x, y = y<<x, y = y>>>x, y = y&x,
y = y^x et y = y|x.
| Précédence | Ordre | Opérateur | Type | Description |
| =, | ||||
| 13 | droite gauche | *=, /=, %=, +=, -=, | Variable, qcq | Affectation simple et |
<<=, >>=, >>>=, |
avec opérations | |||
&=, ^=, |= |
Voici l'opérateur ternaire (le seul). Cette expression est une sorte de si-alors-sinon sous forme d'expression : si la condition e est vraie alors cette expression vaut x sinon elle vaut y.
| Précédence | Ordre | Opérateur | Type | Description |
| 12 | droite gauche | ? : | Booléen, qcq | Si-alors-sinon |
Cet opérateur permet de convertir explicitement le type d'une donnée en un autre type. L'opérateur de parenthèsage () permet de définir l'ordre d'évaluation d'une expression. C'est l'opérateur que l'on utilise traditionnellement. C'est également ce même opérateur qui est utilisé pour encapsuler les paramètres des fonctions. Même lorsqu'une fonction n'a pas d'arguments, ces parenthèses sont requises.
Le problème de la conversion des types se pose lorsqu'une expression est composée de données de nature différentes. Par exemple, quel sens donner à une addition d'un entier et d'un nombre flottant ? Que se passe-t-il lorsqu'on affecte un variable de type entier à une valeur de type caractère ou flottant. La langage Java définit précisément quelles sont les types de données compatibles et quel type de conversion est effectué.
La conversion explicite d'un opérande se fait en le préfixant du type choisi encadré par des parenthèses.
double d = 2.5 ; long l = (long) d ;
Les conversions implicites sont celles faites automatiquement par un compilateur lors de l'évaluation d'une expression (et donc également d'une affectation). Comme nous le verrons plus loin, il y a conversion implicite lors de l'invocation d'une méthode. Il y a deux type de conversion implicite :
long i = 0x7effffffffffffffL ; // 91513144428168478771 float f = i ; // 9.15131e+18 long l = (long)f ; // 91513144428168478772
On utilise la conversion explicite pour changer le type d'une donnée. Ce changement ne peut être arbitraire : seules certaines conversions sont permises. Par exemple, on ne peut convertir un boolean en int mais un double peut être converti en un long.
if (o instanceof C)
| Précédence | Ordre | Opérateur | Type | Description |
| 1 | droite gauche | (type ) | qcq | Changement de type |
| 5 | gauche droite | instanceof | objet | Comporaison de type |
Comme nous le verrons plus loin, les objets complexes et structurés à l'aide des classes. Ces classes sont ``une sorte de struct C ''. Les classes possèdes des champs et des méthodes . L'opérateur d'accès à ces membres des classes est le ``.''.
Nous verrons également que les tableaux sont d'un type
particulier d'objets. Les éléments des tableaux tab sont notés
tab[i]. L'opérateur [] sert d'accès d'opérateur
d'accès aux éléments d'un tableau.
| Précédence | Ordre | Opérateur | Type | Description |
| 1 | droite gauche | ., [] | objet | Accès aux membres |
| Précédence | Ordre | Opérateur | Type | Description |
| 1 | droite gauche | ++, - | Arithmétique | Incrémént et décrément |
| 1 | droite gauche | +, - | Arithmétique | Plus et moins unaire |
| 1 | droite gauche | Entier | complément bit à bit | |
| 1 | droite gauche | ! | Booléen | non booléen |
| 1 | droite gauche | (type) | qcq | Changement de type |
| 1 | droite gauche | ., [] | objet | Accès aux membres |
| 1 | droite gauche | (type) | qcq | Changement de type |
| 2 | gauche droite | *, /, % | Arithmétique | Multiplication, division et reste |
| 3 | gauche droite | +, - | Arithmétique | Addition et soustraction |
| 3 | gauche droite | + | Chaînes de caractères | Concaténation de chaînes |
| 4 | gauche droite | <<, >>, >>> | Entier | Décalage de bits |
| 5 | gauche droite | <,<=, >, >= | Arithmétique | Comparaison arithmétique |
| 5 | gauche droite | instanceof | objet | Comparaison de type |
| 6 | gauche droite | ==, != | objet et type primitif | égalité et différent |
| 7 | gauche droite | Entier et booléen | ET bit à bit et booléen | |
| 8 | gauche droite | ^ |
Entier et booléen | OU exclusif bit à bit et booléen |
| 9 | gauche droite | | | Entier et booléen | Ou bit à bit et booléen |
| 11 | gauche droite | && | Booléen | ET conditionnel |
| 11 | gauche droite | || | Booléen | OU conditionnel |
| 12 | droite gauche | ? : | Booléen, qcq, qcq | Si-alors-sinon |
| =, | ||||
| 13 | droite gauche | *=, /=, %=, +=, -=, | Variable, qcq | Affectation simple et |
<<=, >>=, >>>=, |
avec opérations | |||
&=, ^=, |= |