Création d'un opérateur «logique exclusif ou» en Java

274

Observations:

Java a un opérateur ET logique.
Java a un opérateur OU logique.
Java a un opérateur NOT logique.

Problème:

Selon Sun , Java n'a pas d'opérateur XOR logique . Je voudrais en définir un.

Définition de la méthode:

En tant que méthode, elle est simplement définie comme suit:

public static boolean logicalXOR(boolean x, boolean y) {
    return ( ( x || y ) && ! ( x && y ) );
}


Appel de méthode:

Cette méthode est appelée de la manière suivante:

boolean myVal = logicalXOR(x, y);


Utilisation de l'opérateur:

Je préférerais de loin un opérateur, utilisé comme suit:

boolean myVal = x ^^ y;


Question:

Je ne trouve rien sur la façon de définir un nouvel opérateur en Java. Par où dois-je commencer?

onze81
la source
1
quoi? le lien que vous avez donné a le contenu «OU exclusif au niveau du bit»
Mathew P. Jones
vous demandiez-vous alors si vous pouviez définir des opérateurs en Java comme vous le pouvez en C ++?
avgvstvs
1
Il semble que vous ayez mal compris la différence entre & et &&. Les deux sont des opérateurs logiques (sur un booléen). La réponse de Starblue le couvre plus largement.
Vlasec
juste parce qu'il n'est pas dans le tutoriel , ne signifie pas que Java ne l'a pas - les tutoriels ne sont pas (toujours) complets. Voir la spécification du langage Java 15.22.2
user85421
5
Ça s'appelle !=, il y a aussi un XNOR logique appelé==
Mark K Cowan

Réponses:

695

Java a un opérateur XOR logique , c'est ^ (comme dans a ^ b).

En dehors de cela, vous ne pouvez pas définir de nouveaux opérateurs en Java.

Edit: Voici un exemple:

public static void main(String[] args) {
    boolean[] all = { false, true };
    for (boolean a : all) {
        for (boolean b: all) {
            boolean c = a ^ b;
            System.out.println(a + " ^ " + b + " = " + c);
        }
    }
}

Production:

false ^ false = false
faux ^ vrai = vrai
vrai ^ faux = vrai
vrai ^ vrai = faux
javashlook
la source
5
Cela a également échappé à ma mémoire lorsque j'ai écrit mon article, mais je pense que vous POUVEZ utiliser ^ comme opérateur logique (ainsi que bit à bit).
Neil Coffey
144
^ n'est pas seulement un opérateur au niveau du bit. C'est aussi un opérateur logique. L'opérateur ^ est surchargé. Il fonctionne sur des types intégraux ou des types booléens. +1 pour une excellente réponse javashlook. Eddie, il n'est pas plus explicite que JLS Section 15.22.2, «Opérateurs logiques booléens &, ^ et |».
erickson
97
Et bien sûr, la réponse est que && et || sautera l'évaluation de la 2ème partie de l'expression et & et | évaluera toujours les deux parties de l'expression (d'après ma lecture de JLS). Un ^^ devrait toujours évaluer les deux parties, par définition, se comporte donc de manière identique à ^. Probablement pourquoi il n'y a pas ^^
Eddie
81
@Eddie: Ça et ^^ ressemble trop à une émoticône.
Michael Myers
5
C'est peut-être une question de sémantique, mais en ce qui concerne XOR, au niveau du bit et logique donnent le même résultat. Par conséquent, pas besoin d'opérateurs distincts. La table de vérité simplifiée pour un opérateur XOR est X ^! X = 1. Vous ne pouvez pas court-circuiter une entrée dans XOR car vous devez déterminer si les entrées sont différentes. Il est beaucoup plus facile de comprendre si vous connaissez la fabrication de la porte XOR réelle.
hfontanez
305

N'est-ce pas x! = Y?

Maurice Perry
la source
5
Si x et y sont des booléens, alors la table logique pour xor et! = Sont identiques: t, t => f; t, f => t; f, t => t; f, f => f
Greg Case
81
Maurice: Arrgh tu viens de me couper le souffle! Comment n'ai-je jamais remarqué cela?
8
@Milhous Voulez-vous dire que a != b != ccela ne fonctionnera pas, mais le a ^ b ^ cfera? Dans ce cas, vous vous trompez .
fredoverflow
3
Maurice, tout simplement génial! Il m'arrive de perdre des choses simples de la vue quand il y a beaucoup à faire :)
sberezin
6
Cette approche implose lorsque les deux côtés sont des classes wrapper, new Boolean(true) != new Boolean(true)donne true.
Vlastimil Ovčáčík
74

Java a un opérateur ET logique.
Java a un opérateur OU logique.

Faux.

Java a

  • deux opérateurs ET logiques: ET normal est & et court-circuit ET est &&, et
  • deux opérateurs OR logiques: OR normal est | et OU court-circuit est ||.

XOR existe uniquement en tant que ^, car l'évaluation des courts-circuits n'est pas possible.

starblue
la source
2
Commentaire intéressant. Est-ce documenté?
user666412
1
Je pense & et | ne sont pas en court-circuit car ce sont des opérateurs au niveau du bit. Et en fait, il n'est pas possible de les court-circuiter.
Krzysztof Jabłoński
3
@Krzysztof Jabłoński Ce sont des opérateurs au niveau du bit sur les nombres, mais nous parlons ici d'expressions booléennes.
starblue
3
@ user666412 Oui, dans la spécification du langage Java (où d'autre?).
starblue
18
S'il a 2 opérateurs ET et 2 opérateurs OU, les instructions «Java a un opérateur logique ET» et «Java a un opérateur logique OU» ne sont pas fausses. Par définition, si vous en avez 2, vous en avez également 1.
RyanfaeScotland
31

Vous avez peut-être mal compris la différence entre &et &&, |et || Le but des opérateurs de raccourci &&et ||est que la valeur du premier opérande peut déterminer le résultat et donc le deuxième opérande n'a pas besoin d'être évalué.

Cela est particulièrement utile si le deuxième opérande entraîne une erreur. par exemple

if (set == null || set.isEmpty())
// or
if (list != null && list.size() > 0)

Cependant, avec XOR , vous devez toujours évaluer le deuxième opérande pour obtenir le résultat, de sorte que la seule opération significative soit ^.

Peter Lawrey
la source
20

Vous pouvez simplement écrire (a!=b)

Cela fonctionnerait de la même manière que a ^ b.

Shuliyey
la source
9

C'est parce que la surcharge des opérateurs est quelque chose qu'ils ont spécifiquement laissé de côté délibérément. Ils ont "triché" un peu avec la concaténation de chaînes, mais au-delà, une telle fonctionnalité n'existe pas.

(Avertissement: je n'ai pas travaillé avec les 2 dernières versions majeures de Java, donc si c'est le cas maintenant, je serai très surpris)

Kevin Anderson
la source
5
Gardez à l'esprit que vous ne pouvez pas non plus définir de nouveaux opérateurs en C ++. Tout ce que vous pouvez faire, c'est donner de nouvelles significations aux anciennes.
David Thornley
7

La seule surcharge d'opérateur en Java est + sur les chaînes ( JLS 15.18.1 Opérateur de concaténation des chaînes + ).

La communauté est divisée en 3 depuis des années, 1/3 n'en veut pas, 1/3 le veulent et 1/3 s'en fiche.

Vous pouvez utiliser unicode pour créer des noms de méthode qui sont des symboles ... donc si vous avez un symbole que vous souhaitez utiliser, vous pouvez faire myVal = x. $ (Y); où $ est le symbole et x n'est pas une primitive ... mais cela va être douteux dans certains éditeurs et limite car vous ne pouvez pas le faire sur une primitive.

TofuBeer
la source
7

Le code suivant:

public static boolean logicalXOR(boolean x, boolean y) {
    return ( ( x || y ) && ! ( x && y ) );
}

est superflu.

Pourquoi ne pas écrire:

public static boolean logicalXOR(boolean x, boolean y) {
    return x != y;
}

?

De plus, comme l'a dit javashlook , il y a déjà un ^opérateur.

!=et ^fonctionnent de manière identique * pour les opérandes booléens (votre cas), mais différemment pour les opérandes entiers.

* Notes:
1. Ils fonctionnent de manière identique pour les opérandes boolean(type primitif), mais pas Boolean(type objet). En tant que Boolean(type d'objet), les valeurs peuvent avoir une valeur null. Et !=retournera falseou truelorsque l'un ou les deux de ses opérandes le sont null, tandis que ^jettera NullPointerExceptiondans ce cas.
2. Bien qu'ils fonctionnent de manière identique, ils ont une priorité différente, par exemple lorsqu'ils sont utilisés avec &: a & b != c & dseront traités comme a & (b != c) & d, tandis que a & b ^ c & dseront traités comme (a & b) ^ (c & d)(hors sujet: aïe, le tableau de priorité de style C est nul).

Sasha
la source
1
Pour les valeurs booléennes que j'aime!=
GKalnytskyi
1
@GKalnytskyi pour les Booleanvaleurs ne !=fonctionne pas correctement. Pour les booleanvaleurs c'est ok.
vadipp
2
! = et ^ ne fonctionnent pas de manière identique pour les opérandes booléens. Vous obtiendrez des résultats différents pour "false & false! = True" contre "false & false ^ true" en raison de la priorité.
Albert Hendriks
1
@AlbertHendriks, je ferais mieux de dire qu'ils fonctionnent de manière identique, mais ont une priorité différente (bien que ce soit juste une question de terminologie).
Sasha
6

Voici une méthode var arg XOR pour java ...

public static boolean XOR(boolean... args) {
  boolean r = false;
  for (boolean b : args) {
    r = r ^ b;
  }
  return r;
}

Prendre plaisir

Timothy Jacobsen
la source
On dirait que ça va avoir un comportement très étrange. Par exemple, XOR(true,true,true)renvoie true, ce qui ne ressemble pas à ce que vous attendez d'une méthode appelée XOR. Mon comportement attendu serait qu'il retourne toujours faux (ce qui n'est bien sûr pas utile)
Richard Tingle
5

Logique exclusif ou en Java est appelé !=. Vous pouvez également l'utiliser ^si vous souhaitez confondre vos amis.

Doradus
la source
2

Vous pouvez utiliser Xtend (Infix Operators et Operator Overloading) pour surcharger les opérateurs et «rester» sur Java

iga
la source
Notez que Xtend ne vous permet pas de remplacer le curseur ^; vous devez utiliser bool_1.xor(bool_2). Curieusement, l'analyseur ne vous permet même pas d' utiliser le curseur; vous devez utiliser xorpour les booléens et bitwiseXorpour les entiers. Vous pourriez, bien sûr, surcharger un autre opérateur, mais cela deviendrait très déroutant.
Kelvin
2

Ce que vous demandez n'aurait pas beaucoup de sens. À moins que je ne me trompe, vous suggérez que vous souhaitez utiliser XOR pour effectuer les opérations logiques de la même manière ET et OU. Votre code fourni montre en fait ce à quoi je me réfère:

public static boolean logicalXOR(boolean x, boolean y) {
    return ( ( x || y ) && ! ( x && y ) );
}

Votre fonction a des entrées booléennes et lorsque XOR au niveau du bit est utilisé sur les booléens, le résultat est le même que le code que vous avez fourni. En d'autres termes, XOR au niveau du bit est déjà efficace lors de la comparaison de bits individuels (booléens) ou de la comparaison des bits individuels dans des valeurs plus grandes. Pour mettre cela en contexte, en termes de valeurs binaires, toute valeur non nulle est TRUE et seul ZERO est faux.

Donc, pour que XOR soit appliqué de la même manière que Logical AND est appliqué, vous n'utiliseriez que des valeurs binaires avec un seul bit (donnant le même résultat et la même efficacité) ou la valeur binaire devrait être évaluée dans son ensemble au lieu de par bit. En d'autres termes, l'expression (010 ^^ 110) = FALSE au lieu de (010 ^^ 110) = 100. Cela supprimerait la plupart du sens sémantique de l'opération et représente un test logique que vous ne devriez pas utiliser de toute façon.

user2904660
la source
1

A et B doivent être des valeurs booléennes pour que! = Soit le même que xor afin que la table de vérité soit identique. Vous pouvez également utiliser! (A == B) lol.

John Theibert
la source
1

J'utilise la classe très populaire "org.apache.commons.lang.BooleanUtils"

Cette méthode est testée par de nombreux utilisateurs et sûre. S'amuser. Usage:

boolean result =BooleanUtils.xor(new boolean[]{true,false});
Adam111p
la source
0

Comme le type de données booléen est stocké comme un entier, l'opérateur de bit ^ fonctionne comme une opération XOR s'il est utilisé avec des valeurs booléennes.

//©Mfpl - XOR_Test.java

    public class XOR_Test {
        public static void main (String args[]) {
            boolean a,b;

            a=false; b=false;
            System.out.println("a=false; b=false;  ->  " + (a^b));

            a=false; b=true;
            System.out.println("a=false; b=true;  ->  " + (a^b));

            a=true;  b=false;
            System.out.println("a=true;  b=false;  ->  " + (a^b));

            a=true; b=true;
            System.out.println("a=true; b=true;  ->  " + (a^b));

            /*  output of this program:
                    a=false; b=false;  ->  false
                    a=false; b=true;  ->  true
                    a=true;  b=false;  ->  true
                    a=true; b=true;  ->  false
            */
        }
    }
Conduit sur
la source
0

Voici un exemple:

Étant donné 2 valeurs int, renvoyez true si l'une est négative et l'autre positive. Sauf si le paramètre "négatif" est vrai, ne retournez vrai que si les deux sont négatifs.

    public boolean posNeg(int a, int b, boolean negative) {
      if(!negative){
        return (a>0 && b<0)^(b>0 && a<0);
      }
      else return (a<0 && b<0);
    }
Shadman Sudipto
la source