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 est null ou si la toString() renvoie null , 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 objets String , 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)
  • 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 un Double , le type de résultat est double .
  • Sinon, si l'un des opérandes est un float ou un Float , le type de résultat est float .
  • Sinon, si l'un des opérandes est long ou Long , le type de résultat est long .
  • Sinon, le type de résultat est int . Cela couvre les opérandes byte , short et char 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 pour double , 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 en int , 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 en long est sans perte.
    • La promotion du float pour double 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".

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 et d est une valeur entière q dont la grandeur est la plus grande possible tout en satisfaisant |d ⋅ q| ≤ |n| . De plus, q est positif quand |n| ≥ |d| et n et d ont le même signe, mais q est négatif lorsque |n| ≥ |d| et n et d ont des signes opposés.

Il y a quelques cas particuliers:

  • Si le n est MIN_VALUE et que le diviseur est -1, alors un dépassement d'entier se produit et le résultat est MIN_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 si a / b est positif et
  • sa magnitude est aussi grande que possible sans dépasser l'ampleur du vrai quotient mathématique de a et b .

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èque Math.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:

  1. Si l'un des opérandes est un type encadré, il n'est pas enregistré.
  2. Si l'une des opérandes maintenant un byte , à short ou char , il est promu à un int .
  3. 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".
  4. La comparaison est ensuite effectuée comme suit:
    • Si les opérandes promus sont int ou long les valeurs sont testées pour voir si elles sont identiques.
    • Si les opérandes promus sont float ou double 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.

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:

  1. Si l'un des opérandes est un Boolean , il n'est pas enregistré.
  2. 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é:

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 == est false mais le résultat de != Est true . En effet, le test x != x est true si et seulement si la valeur de x est NaN .

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 de E1 , sauf E1 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 de a + b à la valeur de c 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 que c = 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 que c = 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 que c = 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 que c = 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 que c = c % a

7. <<=

L'opérateur "left shift et assign".

Exemple: c <<= 2 est à peu près le même que c = c << 2

8. >>=

L'opérateur "arithmétique à droite et assigner".

Exemple: c >>= 2 est à peu près la même chose que c = c >> 2

9. >>>=

L'opérateur "décalage droit logique et attribution".

Exemple: c >>>= 2 est à peu près la même chose que c = c >>> 2

10. &=

L'opérateur "bitwise and and assign".

Exemple: c &= 2 est à peu près le même que c = c & 2

11. |=

L'opérateur "bitwise or and assign".

Exemple: c |= 2 est à peu près la même chose que c = c | 2

12. ^=

L'opérateur "bitwise exclusive or and assign".

Exemple: c ^= 2 est à peu près le même que c = 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:

  1. Ces opérateurs nécessitent une valeur int ou long 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 à un byte , à short ou char variable.)

  2. Si vous utilisez un opérateur de décalage avec un premier opérande qui est un byte , char ou short , il est promu à un int et l'opération produit un int .)

  3. 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 .

  4. 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".)

  5. L'opérateur de décalage arithmétique est équivalent en divisant un nombre (complément à deux) par une puissance de 2.

  6. 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:

Java SE 8
  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:

  1. Si l'un des opérandes est un type encadré, il n'est pas enregistré.
  2. Si l'une des opérandes maintenant un byte , à short ou char , il est promu à un int .
  3. 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".
  4. La comparaison est effectuée sur les valeurs int , long , float ou double 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.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow