Java Language
Les opérateurs
Recherche…
Introduction
Les opérateurs en langage de programmation Java sont des symboles spéciaux qui effectuent des opérations spécifiques sur un, deux ou trois opérandes, puis renvoient un résultat.
Remarques
Un opérateur est un symbole (ou des symboles) qui indique à un programme Java d'effectuer une opération sur un, deux ou trois opérandes . Un opérateur et ses opérandes forment une expression (voir la rubrique Expressions). Les opérandes d'un opérateur sont eux-mêmes des expressions.
Cette rubrique décrit les quelque 40 opérateurs distincts définis par Java. La rubrique Expressions séparée explique:
- comment les opérateurs, les opérandes et d'autres choses sont combinés en expressions,
- comment les expressions sont évaluées et
- comment fonctionnent le typage, les conversions et l'évaluation des expressions.
L'opérateur de concaténation de chaînes (+)
Le symbole +
peut signifier trois opérateurs distincts en Java:
- S'il n'y a pas d'opérande avant le
+
, alors c'est l'opérateur unaire Plus. - S'il y a deux opérandes, ils sont tous deux numériques. alors c'est l'opérateur Addition binaire.
- S'il y a deux opérandes et qu'au moins l'un d'eux est une
String
, alors il s'agit de l'opérateur de concaténation binaire.
Dans le cas simple, l'opérateur de concaténation joint deux chaînes pour donner une troisième chaîne. Par exemple:
String s1 = "a String";
String s2 = "This is " + s1; // s2 contains "This is a String"
Lorsque l'un des deux opérandes n'est pas une chaîne, il est converti en une String
comme suit:
Un opérande dont le type est un type primitif est converti comme en appelant
toString()
sur la valeur encadrée.Un opérande dont le type est un type de référence est converti en appelant la
toString()
l'opérande. Si l'opérande estnull
ou si latoString()
renvoienull
, le littéral de chaîne"null"
est utilisé à la place.
Par exemple:
int one = 1;
String s3 = "One is " + one; // s3 contains "One is 1"
String s4 = null + " is null"; // s4 contains "null is null"
String s5 = "{1} is " + new int[]{1}; // s5 contains something like
// "{} is [I@xxxxxxxx"
L'explication de l'exemple s5
est que la toString()
sur les types de tableau est héritée de java.lang.Object
et que le comportement consiste à produire une chaîne composée du nom du type et du code de hachage de l'identité de l'objet.
L'opérateur Concatenation est spécifié pour créer un nouvel objet String
, sauf dans le cas où l'expression est une expression constante. Dans ce dernier cas, l'expression est évaluée au type de compilation et sa valeur d'exécution est équivalente à un littéral de chaîne. Cela signifie qu'il n'y a pas de surcharge d'exécution lors du fractionnement d'un littéral de chaîne longue comme ceci:
String typing = "The quick brown fox " +
"jumped over the " +
"lazy dog"; // constant expression
Optimisation et efficacité
Comme indiqué ci-dessus, à l'exception des expressions constantes, chaque expression de concaténation de chaîne crée un nouvel objet String
. Considérez ce code:
public String stars(int count) {
String res = "";
for (int i = 0; i < count; i++) {
res = res + "*";
}
return res;
}
Dans la méthode ci-dessus, chaque itération de la boucle créera une nouvelle String
un caractère plus longue que l'itération précédente. Chaque concaténation copie tous les caractères des chaînes d'opérandes pour former la nouvelle String
. Ainsi, les stars(N)
vont:
- créer
N
nouveaux objetsString
, et jeter tous sauf le dernier, - copier
N * (N + 1) / 2
caractères, et - générer
O(N^2)
octets de déchets.
C'est très cher pour les gros N
En effet, tout code concaténant des chaînes dans une boucle est susceptible d'avoir ce problème. Une meilleure façon d'écrire ceci serait la suivante:
public String stars(int count) {
// Create a string builder with capacity 'count'
StringBuilder sb = new StringBuilder(count);
for (int i = 0; i < count; i++) {
sb.append("*");
}
return sb.toString();
}
Idéalement, vous devez définir la capacité du StringBuilder
, mais si cela est impossible, la classe se développera automatiquement le tableau de sauvegarde que le constructeur utilise pour tenir des caractères. (Remarque: l'implémentation étend le tableau de support de manière exponentielle. Cette stratégie conserve cette quantité de caractères à un O(N)
plutôt qu'à un O(N^2)
.)
Certaines personnes appliquent ce modèle à toutes les concaténations de chaînes. Cependant, cela n'est pas nécessaire car le JLS permet à un compilateur Java d'optimiser les concaténations de chaînes dans une seule expression. Par exemple:
String s1 = ...;
String s2 = ...;
String test = "Hello " + s1 + ". Welcome to " + s2 + "\n";
sera généralement optimisé par le compilateur bytecode à quelque chose comme ça;
StringBuilder tmp = new StringBuilder();
tmp.append("Hello ")
tmp.append(s1 == null ? "null" + s1);
tmp.append("Welcome to ");
tmp.append(s2 == null ? "null" + s2);
tmp.append("\n");
String test = tmp.toString();
(Le compilateur JIT peut optimiser cela plus loin s'il peut en déduire que s1
ou s2
ne peut pas être null
.) Mais notez que cette optimisation n'est autorisée que dans une seule expression.
En bref, si vous êtes préoccupé par l'efficacité des concaténations de chaînes:
- Effectuez une optimisation manuelle si vous effectuez une concaténation répétée dans une boucle (ou similaire).
- Ne pas optimiser manuellement une seule expression de concaténation.
Les opérateurs arithmétiques (+, -, *, /,%)
Le langage Java fournit 7 opérateurs effectuant des opérations arithmétiques sur des valeurs entières et à virgule flottante.
- Il y a deux opérateurs
+
:- L'opérateur d'addition binaire ajoute un numéro à un autre. (Il y a aussi un opérateur binaire
+
qui effectue la concaténation des chaînes. Ceci est décrit dans un exemple séparé.) - L'opérateur unaire plus ne fait rien d'autre que déclencher une promotion numérique (voir ci-dessous)
- L'opérateur d'addition binaire ajoute un numéro à un autre. (Il y a aussi un opérateur binaire
- Il y a deux
-
opérateurs:- L'opérateur de soustraction binaire soustrait un nombre d'un autre.
- L'opérateur moins unaire équivaut à soustraire son opérande de zéro.
- L'opérateur de multiplication binaire (*) multiplie un nombre par un autre.
- L'opérateur de division binaire (/) divise un nombre par un autre.
- L'opérateur binaire reste 1 (%) calcule le reste lorsqu'un nombre est divisé par un autre.
1. Ceci est souvent appelé à tort l'opérateur "module". "Reste" est le terme utilisé par JLS. "Module" et "reste" ne sont pas la même chose.
Opérande et types de résultats, et promotion numérique
Les opérateurs nécessitent des opérandes numériques et produisent des résultats numériques. Les types d'opérandes peuvent être tous les types numériques primitifs ( byte
, caractères short
, caractères char
, int
, long
, float
ou double
) ou tout type d'encapsuleur numérique défini dans java.lang
; à savoir ( Byte
, Character
, Short
, Integer
, Long
, Float
ou Double
.
Le type de résultat est déterminé sur la base des types de l'opérande ou des opérandes, comme suit:
- Si l'un des opérandes est un
double
ou unDouble
, le type de résultat estdouble
. - Sinon, si l'un des opérandes est un
float
ou unFloat
, le type de résultat estfloat
. - Sinon, si l'un des opérandes est
long
ouLong
, le type de résultat estlong
. - Sinon, le type de résultat est
int
. Cela couvre les opérandesbyte
,short
etchar
ainsi que `int.
Le type de résultat de l'opération détermine comment l'opération arithmétique est effectuée et comment les opérandes sont traités
- Si le type de résultat est
double
, les opérandes sont promus pourdouble
, et l'opération est effectuée en utilisant l'arithmétique à virgule flottante IEE 754 64 bits (double précision binaire). - Si le type de résultat est
float
, les opérandes sont promus àfloat
et l'opération est effectuée en utilisant l'arithmétique à virgule flottante IEE 754 32 bits (binaire simple précision). - Si le type de résultat est
long
, les opérandes sont promus àlong
et l'opération est effectuée en utilisant l'arithmétique d'entier binaire à deux compléments signés 64 bits. - Si le type de résultat est
int
, les opérandes sont promus enint
, et l'opération est effectuée en utilisant une arithmétique d'entiers binaires à deux compléments signés 32 bits.
La promotion se déroule en deux étapes:
- Si le type d'opérande est un type wrapper, la valeur de l'opérande est unboxed à une valeur du type primitif correspondant.
- Si nécessaire, le type primitif est promu au type requis:
- La promotion des entiers en
int
ou enlong
est sans perte. - La promotion du
float
pourdouble
est sans perte. - La promotion d'un entier sur une valeur à virgule flottante peut entraîner une perte de précision. La conversion est effectuée en utilisant la sémantique IEE 768 "round-to-close".
- La promotion des entiers en
Le sens de la division
L'opérateur / divise l'opérande gauche n
(dividende) et l'opérande de droite d
(le diviseur) et produit le résultat q
(quotient).
La division Java entière arrondit vers zéro. La section JLS 15.17.2 spécifie le comportement de la division entière Java comme suit:
Le quotient produit pour les opérandes
n
etd
est une valeur entièreq
dont la grandeur est la plus grande possible tout en satisfaisant|d ⋅ q| ≤ |n|
. De plus,q
est positif quand|n| ≥ |d|
etn
etd
ont le même signe, maisq
est négatif lorsque|n| ≥ |d|
etn
etd
ont des signes opposés.
Il y a quelques cas particuliers:
- Si le
n
estMIN_VALUE
et que le diviseur est -1, alors un dépassement d'entier se produit et le résultat estMIN_VALUE
. Aucune exception n'est levée dans ce cas. - Si
d
vaut 0, alors `ArithmeticException est levée.
La division en virgule flottante Java a plus de cas à prendre en compte. Cependant, l'idée de base est que le résultat q
est la valeur la plus proche de la satisfaction d . q = n
.
La division en virgule flottante ne donnera jamais lieu à une exception. Au lieu de cela, les opérations qui divisent par zéro donnent des valeurs INF et NaN; voir ci-dessous.
La signification du reste
Contrairement à C et C ++, l'opérateur restant en Java fonctionne à la fois avec des opérations à nombre entier et à virgule flottante.
Pour les cas entiers, le résultat d' a % b
est défini comme étant le nombre r
tel que (a / b) * b + r
est égal à a
, où /
, *
et +
sont les opérateurs entiers Java appropriés. Cela s'applique dans tous les cas sauf lorsque b
est égal à zéro. Ce cas, reste reste une ArithmeticException
.
Il résulte de la définition ci-dessus qu'un a % b
ne peut être négatif que si a
est négatif, et qu'il ne soit positif que si a
est positif. De plus, l’ampleur d’ a % b
est toujours inférieure à l’ampleur de b
.
L'opération de reste à virgule flottante est une généralisation de la casse entière. Le résultat d' a % b
est le reste r
est défini par la relation mathématique r = a - (b ⋅ q)
où:
-
q
est un entier, - il est négatif uniquement si
a / b
est négatif et positif uniquement sia / b
est positif et - sa magnitude est aussi grande que possible sans dépasser l'ampleur du vrai quotient mathématique de
a
etb
.
Le reste à virgule flottante peut produire des valeurs INF
et NaN
dans les cas limites tels que lorsque b
est égal à zéro; voir ci-dessous. Il ne jettera pas une exception.
Note importante:
Le résultat d'une opération de reste à virgule flottante calculée par
%
n'est pas le même que celui produit par l'opération restante définie par IEEE 754. Le reste de l'IEEE 754 peut être calculé à l'aide de la méthode de bibliothèqueMath.IEEEremainder
.
Débordement d'entier
Les valeurs entières de Java 32 et 64 bits sont signées et utilisent une représentation binaire en complément à deux. Par exemple, la gamme des nombres représentables comme (32 bits) int
-2 31 à 2 31-1.
Lorsque vous ajoutez, soustrayez ou plusieurs deux entiers N bits (N == 32 ou 64), le résultat de l'opération peut être trop important pour représenter un entier N bits. Dans ce cas, l'opération entraîne un débordement d'entier et le résultat peut être calculé comme suit:
- L'opération mathématique est effectuée pour donner une représentation intermédiaire à deux complément du nombre entier. Cette représentation sera supérieure à N bits.
- Les 32 ou 64 bits inférieurs de la représentation intermédiaire sont utilisés comme résultat.
Il convient de noter que le débordement d'entier n'entraîne en aucun cas des exceptions.
Valeurs INF et NAN en virgule flottante
Java utilise des représentations à virgule flottante IEE 754 pour float
et double
. Ces représentations ont des valeurs spéciales pour représenter des valeurs qui ne relèvent pas du domaine des nombres réels:
- Les valeurs infinies ou INF indiquent des nombres trop importants. La valeur
+INF
indique des nombres trop grands et positifs. La valeur-INF
indique des nombres trop grands et négatifs. - Les "indéfinis" / "pas un nombre" ou NaN désignent des valeurs résultant d'opérations sans signification.
Les valeurs INF sont produites par des opérations flottantes qui provoquent un débordement ou par division par zéro.
Les valeurs NaN sont produites en divisant zéro par zéro ou en calculant le reste zéro.
Étonnamment, il est possible d'effectuer des opérations arithmétiques à l'aide des opérandes INF et NaN sans provoquer d'exceptions. Par exemple:
- Ajouter + INF et une valeur finie donne + INF.
- Ajouter + INF et + INF donne + INF.
- Ajouter + INF et -INF donne NaN.
- La division par INF donne +0.0 ou -0.0.
- Toutes les opérations avec un ou plusieurs opérandes NaN donnent NaN.
Pour plus de détails, veuillez vous référer aux sous-sections pertinentes de JLS 15 . Notez que c'est largement "académique". Pour les calculs typiques, un INF
ou NaN
signifie que quelque chose ne va pas; Par exemple, vous avez des données d'entrée incomplètes ou incorrectes, ou le calcul a été programmé de manière incorrecte.
Les opérateurs d'égalité (==,! =)
Les opérateurs ==
et !=
Sont des opérateurs binaires dont la valeur est true
ou false
selon que les opérandes sont égaux ou non. L'opérateur ==
donne true
si les opérandes sont égaux et false
sinon. L'opérateur !=
Donne false
si les opérandes sont égaux et true
sinon.
Ces opérateurs peuvent être utilisés avec des opérandes avec des types primitifs et de référence, mais le comportement est sensiblement différent. Selon le JLS, il existe en réalité trois ensembles distincts de ces opérateurs:
- Les booléens
==
et les opérateurs!=
. - Les opérateurs numériques
==
et!=
. - Les opérateurs de référence
==
et!=
.
Cependant, dans tous les cas, le type de résultat des opérateurs ==
et !=
Est boolean
.
Les opérateurs numériques ==
et !=
Lorsque l'un (ou les deux) opérandes d'un opérateur ==
ou !=
Est un type numérique primitif ( byte
, short
, char
, int,
long
, float
ou double
), l'opérateur est une comparaison numérique. Le second opérande doit être un type numérique primitif ou un type numérique encadré.
Le comportement des autres opérateurs numériques est le suivant:
- Si l'un des opérandes est un type encadré, il n'est pas enregistré.
- Si l'une des opérandes maintenant un
byte
, àshort
ouchar
, il est promu à unint
. - Si les types des opérandes ne sont pas les mêmes, l'opérande avec le type "plus petit" est promu au type "plus grand".
- La comparaison est ensuite effectuée comme suit:
- Si les opérandes promus sont
int
oulong
les valeurs sont testées pour voir si elles sont identiques. - Si les opérandes promus sont
float
oudouble
alors:- les deux versions de zéro (
+0.0
et-0.0
) sont considérés comme égaux - une valeur
NaN
est traitée comme non égal à rien, et - les autres valeurs sont égales si leurs représentations IEEE 754 sont identiques.
- les deux versions de zéro (
- Si les opérandes promus sont
Remarque: vous devez faire attention lorsque vous utilisez ==
et !=
Pour comparer des valeurs en virgule flottante.
Le booléen ==
et les opérateurs !=
Si les deux opérandes sont boolean
, ou l'un est boolean
et l'autre Boolean
, ces opérateurs sont les opérateurs booléens ==
et !=
. Le comportement est le suivant:
- Si l'un des opérandes est un
Boolean
, il n'est pas enregistré. - Les opérandes unboxed sont testés et le résultat booléen est calculé selon la table de vérité suivante
UNE | B | A == B | A! = B |
---|---|---|---|
faux | faux | vrai | faux |
faux | vrai | faux | vrai |
vrai | faux | faux | vrai |
vrai | vrai | vrai | faux |
Il y a deux «pièges» qui recommandent d'utiliser ==
et !=
Avec parcimonie avec des valeurs de vérité:
Si vous utilisez
==
ou!=
Pour comparer deux objetsBoolean
, les opérateurs de référence sont utilisés. Cela peut donner un résultat inattendu. voir Pitfall: utiliser == pour comparer des objets primitifs tels que EntierL'opérateur
==
peut facilement être tapé comme=
. Pour la plupart des types d'opérandes, cette erreur entraîne une erreur de compilation. Cependant, pourBoolean
opérandesboolean
etBoolean
l'erreur conduit à un comportement d'exécution incorrect; voir Pitfall - Utiliser '==' pour tester une valeur booléenne
La référence ==
et les opérateurs !=
Si les deux opérandes sont des références d'objet, les opérateurs ==
et !=
Testent si les deux opérandes font référence au même objet . Ce n'est souvent pas ce que vous voulez. Pour tester si deux objets sont égaux en valeur , la méthode .equals()
doit être utilisée à la place.
String s1 = "We are equal";
String s2 = new String("We are equal");
s1.equals(s2); // true
// WARNING - don't use == or != with String values
s1 == s2; // false
Attention: utiliser ==
et !=
Pour comparer les valeurs de String
est incorrect dans la plupart des cas; voir http://www.riptutorial.com/java/example/16290/pitfall--using----to-compare-strings . Un problème similaire s'applique aux types d'encapsuleurs primitifs. voir http://www.riptutorial.com/java/example/8996/pitfall--using----to-compare-primitive-wrappers-objects-such-as-integer .
À propos des bordures NaN
JLS 15.21.1 indique ce qui suit:
Si l'un des opérandes est
NaN
, le résultat de==
estfalse
mais le résultat de!=
Esttrue
. En effet, le testx != x
esttrue
si et seulement si la valeur dex
estNaN
.
Ce comportement est (pour la plupart des programmeurs) inattendu. Si vous testez si une valeur NaN
est égale à elle-même, la réponse est "Non, ça ne l'est pas!". En d'autres termes, ==
n'est pas réflexif pour les valeurs NaN
.
Cependant, il ne s'agit pas d'une "bizarrerie" Java, ce comportement est spécifié dans les normes à virgule flottante IEEE 754 et vous constaterez qu'il est implémenté par la plupart des langages de programmation modernes. (Pour plus d'informations, voir http://stackoverflow.com/a/1573715/139985 ... notant que ceci est écrit par quelqu'un qui était "dans la pièce lorsque les décisions ont été prises"!)
Les opérateurs d'incrémentation / décrémentation (++ / -)
Les variables peuvent être incrémentées ou décrémentées de 1 en utilisant respectivement les opérateurs ++
et --
.
Lorsque les opérateurs ++
et --
suivent des variables, ils sont appelés respectivement post-incrémentation et post-décrémentation .
int a = 10;
a++; // a now equals 11
a--; // a now equals 10 again
Lorsque les opérateurs ++
et --
précèdent les variables, les opérations sont appelées pré-incrémentation et pré-décrémentation respectivement.
int x = 10;
--x; // x now equals 9
++x; // x now equals 10
Si l'opérateur précède la variable, la valeur de l'expression est la valeur de la variable après incrémentation ou décrémentation. Si l'opérateur suit la variable, la valeur de l'expression est la valeur de la variable avant d'être incrémentée ou décrémentée.
int x=10;
System.out.println("x=" + x + " x=" + x++ + " x=" + x); // outputs x=10 x=10 x=11
System.out.println("x=" + x + " x=" + ++x + " x=" + x); // outputs x=11 x=12 x=12
System.out.println("x=" + x + " x=" + x-- + " x=" + x); // outputs x=12 x=12 x=11
System.out.println("x=" + x + " x=" + --x + " x=" + x); // outputs x=11 x=10 x=10
Veillez à ne pas écraser les post-incréments ou les décréments. Cela se produit si vous utilisez un opérateur de post-in / decrement à la fin d'une expression qui est réaffecté à la variable in / decremented elle-même. Le in / decrement n'aura aucun effet. Même si la variable du côté gauche est incrémentée correctement, sa valeur sera immédiatement remplacée par le résultat précédemment évalué du côté droit de l'expression:
int x = 0;
x = x++ + 1 + x++; // x = 0 + 1 + 1
// do not do this - the last increment has no effect (bug!)
System.out.println(x); // prints 2 (not 3!)
Correct:
int x = 0;
x = x++ + 1 + x; // evaluates to x = 0 + 1 + 1
x++; // adds 1
System.out.println(x); // prints 3
L'opérateur conditionnel (? :)
Syntaxe
{condition à évaluer} ? {statement-execute-on-true} : {statement-execute-on-false}
Comme indiqué dans la syntaxe, l'opérateur conditionnel (également appelé opérateur ternaire 1 ) utilise le ?
(point d'interrogation) et :
(deux-points) caractères pour permettre une expression conditionnelle de deux résultats possibles. Il peut être utilisé pour remplacer des blocs if-else
plus longs pour renvoyer l'une des deux valeurs en fonction de la condition.
result = testCondition ? value1 : value2
Est équivalent à
if (testCondition) {
result = value1;
} else {
result = value2;
}
Il peut être lu comme suit: «Si testCondition est true, définissez result sur value1; sinon, définissez le résultat sur valeur2 ”.
Par exemple:
// get absolute value using conditional operator
a = -10;
int absValue = a < 0 ? -a : a;
System.out.println("abs = " + absValue); // prints "abs = 10"
Est équivalent à
// get absolute value using if/else loop
a = -10;
int absValue;
if (a < 0) {
absValue = -a;
} else {
absValue = a;
}
System.out.println("abs = " + absValue); // prints "abs = 10"
Usage courant
Vous pouvez utiliser l'opérateur conditionnel pour les affectations conditionnelles (comme la vérification null).
String x = y != null ? y.toString() : ""; //where y is an object
Cet exemple est équivalent à:
String x = "";
if (y != null) {
x = y.toString();
}
Étant donné que l'opérateur conditionnel a la deuxième priorité la plus basse, au-dessus des opérateurs d'affectation , il est rarement nécessaire d'utiliser des parenthèses autour de la condition , mais des parenthèses sont nécessaires dans toute la structure de l'opérateur conditionnel lorsqu'il est associé à d'autres opérateurs:
// no parenthesis needed for expressions in the 3 parts
10 <= a && a < 19 ? b * 5 : b * 7
// parenthesis required
7 * (a > 0 ? 2 : 5)
Les opérateurs conditionnels peuvent également être imbriqués dans la troisième partie, où ils fonctionnent plus comme un chaînage ou comme une instruction switch.
a ? "a is true" :
b ? "a is false, b is true" :
c ? "a and b are false, c is true" :
"a, b, and c are false"
//Operator precedence can be illustrated with parenthesis:
a ? x : (b ? y : (c ? z : w))
Note de bas de page:
1 - La spécification de langage Java et le didacticiel Java appellent tous deux l'opérateur ( ? :
:) L'opérateur conditionnel . Le tutoriel dit qu'il est "également connu sous le nom d'opérateur ternaire" car il est (actuellement) le seul opérateur ternaire défini par Java. La terminologie "opérateur conditionnel" est cohérente avec C et C ++ et les autres langages avec un opérateur équivalent.
Les opérateurs binaires et logiques (~, &, |, ^)
Le langage Java fournit 4 opérateurs qui effectuent des opérations binaires ou logiques sur des opérandes entiers ou booléens.
- L'opérateur complément (
~
) est un opérateur unaire qui effectue une inversion binaire ou logique des bits d'un opérande; voir JLS 15.15.5. . - L'opérateur AND (
&
) est un opérateur binaire qui effectue un "et" deux bits ou logique de deux opérandes; voir JLS 15.22.2. . - L'opérateur OR (
|
) est un opérateur binaire qui exécute un "inclusive" ou deux "opérandes" binaire ou logique; voir JLS 15.22.2. . - L'opérateur XOR (
^
) est un opérateur binaire qui effectue une opération "exclusive ou" binaire ou logique de deux opérandes; voir JLS 15.22.2. .
Les opérations logiques effectuées par ces opérateurs lorsque les opérandes sont des booléens peuvent être résumées comme suit:
UNE | B | ~ A | UN B | Un | B | A ^ B |
---|---|---|---|---|---|
0 | 0 | 1 | 0 | 0 | 0 |
0 | 1 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 0 | 1 | 1 |
1 | 1 | 0 | 1 | 1 | 0 |
Notez que pour les opérandes entiers, le tableau ci-dessus décrit ce qui se passe pour les bits individuels. Les opérateurs fonctionnent en fait sur les 32 ou 64 bits de l'opérande ou des opérandes en parallèle.
Types d'opérandes et types de résultats.
Les conversions arithmétiques habituelles s'appliquent lorsque les opérandes sont des entiers. Cas d'utilisation courants pour les opérateurs binaires
L'opérateur ~
est utilisé pour inverser une valeur booléenne ou modifier tous les bits d'un opérande entier.
L'opérateur &
est utilisé pour "masquer" certains bits d'un opérande entier. Par exemple:
int word = 0b00101010;
int mask = 0b00000011; // Mask for masking out all but the bottom
// two bits of a word
int lowBits = word & mask; // -> 0b00000010
int highBits = word & ~mask; // -> 0b00101000
Le |
L'opérateur est utilisé pour combiner les valeurs de vérité de deux opérandes. Par exemple:
int word2 = 0b01011111;
// Combine the bottom 2 bits of word1 with the top 30 bits of word2
int combined = (word & mask) | (word2 & ~mask); // -> 0b01011110
L'opérateur ^
est utilisé pour basculer ou "retourner" les bits:
int word3 = 0b00101010;
int word4 = word3 ^ mask; // -> 0b00101001
Pour plus d'exemples d'utilisation des opérateurs binaires , voir Manipulation des bits
L'opérateur d'instance
Cet opérateur vérifie si l'objet est d'un type de classe / interface particulier. L' opérateur instanceof est écrit comme suit:
( Object reference variable ) instanceof (class/interface type)
Exemple:
public class Test {
public static void main(String args[]){
String name = "Buyya";
// following will return true since name is type of String
boolean result = name instanceof String;
System.out.println( result );
}
}
Cela produirait le résultat suivant:
true
Cet opérateur retournera toujours true si l'objet comparé est l'affectation compatible avec le type à droite.
Exemple:
class Vehicle {}
public class Car extends Vehicle {
public static void main(String args[]){
Vehicle a = new Car();
boolean result = a instanceof Car;
System.out.println( result );
}
}
Cela produirait le résultat suivant:
true
Les opérateurs d'affectation (=, + =, - =, * =, / =,% =, << =, >> =, >>> =, & =, | = et ^ =)
L'opérande de gauche pour ces opérateurs doit être soit une variable non finale, soit un élément d'un tableau. L'opérande de droite doit être compatible avec l'opérande de gauche. Cela signifie que soit les types doivent être identiques, soit le type d'opérande droit doit être convertible en type d'opérandes gauche par une combinaison de boxing, unboxing ou élargissement. (Pour plus de détails, reportez-vous à JLS 5.2 .)
La signification précise des opérateurs "operation and assign" est spécifiée par JLS 15.26.2 comme suit :
Une expression d'affectation composée de la forme
E1 op= E2
est équivalente àE1 = (T) ((E1) op (E2))
, oùT
est le type deE1
, saufE1
n'est évaluée qu'une seule fois.
Notez qu'il existe un type implicite avant l'assignation finale.
1. =
L'opérateur d'affectation simple: attribue la valeur de l'opérande de droite à l'opérande de gauche.
Exemple:
c = a + b
va ajouter la valeur dea + b
à la valeur dec
et l'assigner àc
2. +=
L'opérateur "add and assign": ajoute la valeur de l'opérande de droite à la valeur de l'opérande de gauche et affecte le résultat à l'opérande de gauche. Si l'opérande de gauche a le type String
, alors c'est un opérateur "concatenate and assign".
Exemple:
c += a
est sensiblement le même quec = c + a
3. -=
L'opérateur "soustraire et affecter": soustrait la valeur de l'opérande droite de la valeur de l'opérande de gauche et attribue le résultat à l'opérande de gauche.
Exemple:
c -= a
est sensiblement le même quec = c - a
4. *=
L'opérateur "multiplier et affecter": multiplie la valeur de l'opérande de droite par la valeur de l'opérande de gauche et attribue le résultat à l'opérande de gauche. .
Exemple:
c *= a
est sensiblement le même quec = c * a
5. /=
L'opérateur "diviser et assigner": divise la valeur de l'opérande de droite par la valeur de l'opérande de gauche et attribue le résultat à l'opérande de gauche.
Exemple:
c /*= a
est sensiblement le même quec = c / a
6. %=
L'opérateur "modulus and assign": calcule le module de la valeur de l'opérande de droite par la valeur de l'opérande de gauche et attribue le résultat à l'opérande de gauche.
Exemple:
c %*= a
est sensiblement le même quec = c % a
7. <<=
L'opérateur "left shift et assign".
Exemple:
c <<= 2
est à peu près le même quec = c << 2
8. >>=
L'opérateur "arithmétique à droite et assigner".
Exemple:
c >>= 2
est à peu près la même chose quec = c >> 2
9. >>>=
L'opérateur "décalage droit logique et attribution".
Exemple:
c >>>= 2
est à peu près la même chose quec = c >>> 2
10. &=
L'opérateur "bitwise and and assign".
Exemple:
c &= 2
est à peu près le même quec = c & 2
11. |=
L'opérateur "bitwise or and assign".
Exemple:
c |= 2
est à peu près la même chose quec = c | 2
12. ^=
L'opérateur "bitwise exclusive or and assign".
Exemple:
c ^= 2
est à peu près le même quec = c ^ 2
Les opérateurs conditionnels et et / ou conditionnels (&& et ||)
Java fournit un opérateur conditionnel et un opérateur conditionnel ou conditionnel, qui prennent tous deux un ou deux opérandes de type boolean
et produisent un résultat boolean
. Ceux-ci sont:
&&
- l'opérateur AND conditionnel,||
- les opérateurs conditionnels-OU. L’évaluation de<left-expr> && <right-expr>
est équivalente au pseudo-code suivant:{ boolean L = evaluate(<left-expr>); if (L) { return evaluate(<right-expr>); } else { // short-circuit the evaluation of the 2nd operand expression return false; } }
L'évaluation de <left-expr> || <right-expr>
est équivalent au pseudo-code suivant:
{
boolean L = evaluate(<left-expr>);
if (!L) {
return evaluate(<right-expr>);
} else {
// short-circuit the evaluation of the 2nd operand expression
return true;
}
}
Comme le montre le pseudo-code ci-dessus, le comportement des opérateurs de court-circuit équivaut à utiliser des instructions if
/ else
.
Exemple - utilisation de && comme garde dans une expression
L'exemple suivant montre le modèle d'utilisation le plus courant pour l'opérateur &&
. Comparez ces deux versions d'une méthode pour tester si un Integer
fourni est zéro.
public boolean isZero(Integer value) {
return value == 0;
}
public boolean isZero(Integer value) {
return value != null && value == 0;
}
La première version fonctionne dans la plupart des cas, mais si l'argument value
est null
, une NullPointerException
sera lancée.
Dans la deuxième version, nous avons ajouté un test de "garde". La value != null && value == 0
expression est évaluée en exécutant d'abord le test value != null
. Si le test null
réussit (c.-à-d. Qu'il est évalué à true
), l'expression value == 0
est évaluée. Si le test null
échoue, alors l'évaluation de la value == 0
est ignorée (court-circuitée) et nous n'obtenons pas une NullPointerException
.
Exemple - utilisation de && pour éviter un calcul coûteux
L'exemple suivant montre comment &&
peut être utilisé pour éviter un calcul relativement coûteux:
public boolean verify(int value, boolean needPrime) {
return !needPrime | isPrime(value);
}
public boolean verify(int value, boolean needPrime) {
return !needPrime || isPrime(value);
}
Dans la première version, les deux opérandes du |
sera toujours évalué, donc la méthode (coûteuse) isPrime
sera appelée inutilement. La deuxième version évite l'appel inutile en utilisant ||
au lieu de |
.
Les opérateurs de quart (<<, >> et >>>)
Le langage Java fournit trois opérateurs pour effectuer un décalage binaire sur des valeurs entières de 32 et 64 bits. Ce sont tous des opérateurs binaires, le premier opérande étant la valeur à déplacer et le second opérande indiquant la distance à déplacer.
Le
<<
ou l' opérateur de décalage vers la gauche déplace la valeur donnée par le premier opérande vers la gauche par le nombre de positions de bits fournis par le deuxième opérande. Les positions vides à droite sont remplies de zéros.L'opérateur de décalage « arithmétique » ou « arithmétique» décale la valeur donnée par le premier opérande vers la droite du nombre de positions binaires données par le second opérande. Les positions vides à gauche sont remplies en copiant le bit le plus à gauche. Ce processus est appelé extension de signe .
L'opérateur de décalage à droite ">>>" ou logique déplace la valeur donnée par le premier opérande vers la droite par le nombre de positions de bits fournies par le second opérande. Les positions vides à gauche sont remplies de zéros.
Remarques:
Ces opérateurs nécessitent une valeur
int
oulong
comme premier opérande et produisent une valeur du même type que le premier opérande. (Vous aurez besoin d'utiliser une distribution de type explicite lors de l' affectation du résultat d'un passage à unbyte
, àshort
ouchar
variable.)Si vous utilisez un opérateur de décalage avec un premier opérande qui est un
byte
,char
oushort
, il est promu à unint
et l'opération produit unint
.)Le second opérande est réduit modulo par le nombre de bits de l'opération pour donner la valeur du décalage. Pour plus d'informations sur le concept mathématique des mods , voir Exemples de modules .
Les bits décalés de l'extrémité gauche ou droite par l'opération sont ignorés. (Java ne fournit pas un opérateur primitif "rotate".)
L'opérateur de décalage arithmétique est équivalent en divisant un nombre (complément à deux) par une puissance de 2.
L'opérateur de décalage de gauche est équivalent en multipliant un nombre (complément à deux) par une puissance de 2.
Le tableau suivant vous aidera à voir les effets des trois opérateurs de quart. (Les nombres ont été exprimés en notation binaire pour faciliter la visualisation.)
Opérande1 | Opérande2 | << | >> | >>> |
---|---|---|---|---|
0b0000000000001011 | 0 | 0b0000000000001011 | 0b0000000000001011 | 0b0000000000001011 |
0b0000000000001011 | 1 | 0b0000000000010110 | 0b0000000000000101 | 0b0000000000000101 |
0b0000000000001011 | 2 | 0b0000000000101100 | 0b0000000000000010 | 0b0000000000000010 |
0b0000000000001011 | 28 | 0b1011000000000000 | 0b0000000000000000 | 0b0000000000000000 |
0b0000000000001011 | 31 | 0b1000000000000000 | 0b0000000000000000 | 0b0000000000000000 |
0b0000000000001011 | 32 | 0b0000000000001011 | 0b0000000000001011 | 0b0000000000001011 |
... | ... | ... | ... | ... |
0b1000000000001011 | 0 | 0b1000000000001011 | 0b1000000000001011 | 0b1000000000001011 |
0b1000000000001011 | 1 | 0b0000000000010110 | 0b1100000000000101 | 0b0100000000000101 |
0b1000000000001011 | 2 | 0b0000000000101100 | 0b1110000000000010 | 0b00100000000000100 |
0b1000000000001011 | 31 | 0b1000000000000000 | 0b1111111111111111 | 0b0000000000000001 |
Il y a des exemples de l'utilisateur des opérateurs de décalage dans la manipulation de bits
L'opérateur Lambda (->)
A partir de Java 8, l'opérateur Lambda ( ->
) est l'opérateur utilisé pour introduire une expression Lambda. Il existe deux syntaxes communes, comme illustré par ces exemples:
a -> a + 1 // a lambda that adds one to its argument
a -> { return a + 1; } // an equivalent lambda using a block.
Une expression lambda définit une fonction anonyme ou, plus correctement, une instance d'une classe anonyme qui implémente une interface fonctionnelle .
(Cet exemple est inclus ici pour être complet. Reportez-vous à la rubrique Expressions Lambda pour le traitement complet.)
Les opérateurs relationnels (<, <=,>,> =)
Les opérateurs <
, <=
, >
et >=
sont des opérateurs binaires permettant de comparer des types numériques. La signification des opérateurs est celle que vous attendez. Par exemple, si a
et b
sont déclarés comme byte
, short
, char
, int
, long
, float
, double
ou les types de boîte correspondants:
- `a < b` tests if the value of `a` is less than the value of `b`.
- `a <= b` tests if the value of `a` is less than or equal to the value of `b`.
- `a > b` tests if the value of `a` is greater than the value of `b`.
- `a >= b` tests if the value of `a` is greater than or equal to the value of `b`.
Le type de résultat pour ces opérateurs est boolean
dans tous les cas.
Les opérateurs relationnels peuvent être utilisés pour comparer des nombres de types différents. Par exemple:
int i = 1;
long l = 2;
if (i < l) {
System.out.println("i is smaller");
}
Les opérateurs relationnels peuvent être utilisés lorsque l'un ou les deux nombres sont des instances de types numériques encadrés. Par exemple:
Integer i = 1; // 1 is autoboxed to an Integer
Integer j = 2; // 2 is autoboxed to an Integer
if (i < j) {
System.out.println("i is smaller");
}
Le comportement précis est résumé comme suit:
- Si l'un des opérandes est un type encadré, il n'est pas enregistré.
- Si l'une des opérandes maintenant un
byte
, àshort
ouchar
, il est promu à unint
. - Si les types des opérandes ne sont pas les mêmes, l'opérande avec le type "plus petit" est promu au type "plus grand".
- La comparaison est effectuée sur les valeurs
int
,long
,float
oudouble
résultantes.
Vous devez faire attention aux comparaisons relationnelles impliquant des nombres à virgule flottante:
- Les expressions qui calculent des nombres à virgule flottante entraînent souvent des erreurs d'arrondi du fait que les représentations à virgule flottante de l'ordinateur ont une précision limitée.
- Lorsque vous comparez un type entier et un type à virgule flottante, la conversion de l'entier en virgule flottante peut également entraîner des erreurs d'arrondi.
Enfin, Java ne prend pas en charge l'utilisation d'opérateurs relationnels avec d'autres types que ceux répertoriés ci-dessus. Par exemple, vous ne pouvez pas utiliser ces opérateurs pour comparer des chaînes, des tableaux de nombres, etc.