Erstellen eines "logischen Exklusiv- oder" -Operators in Java

274

Beobachtungen:

Java hat einen logischen UND-Operator.
Java hat einen logischen ODER-Operator.
Java hat einen logischen NOT-Operator.

Problem:

Laut Sun hat Java keinen logischen XOR-Operator . Ich möchte einen definieren.

Methodendefinition:

Als Methode wird es einfach wie folgt definiert:

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


Methodenaufruf:

Diese Methode wird folgendermaßen aufgerufen:

boolean myVal = logicalXOR(x, y);


Bedienerbetrieb:

Ich hätte viel lieber einen Operator, der wie folgt verwendet wird:

boolean myVal = x ^^ y;


Frage:

Ich kann nichts darüber finden, wie man einen neuen Operator in Java definiert. Wo soll ich anfangen?

elf81
quelle
1
Was? Der Link, den Sie gegeben haben, hat den Inhalt 'bitweise exklusives ODER'
Mathew P. Jones
Haben Sie sich damals gefragt, ob Sie Operatoren in Java wie in C ++ definieren könnten?
avgvstvs
1
Anscheinend haben Sie den Unterschied zwischen & und && falsch verstanden. Beide sind logische Operatoren (auf einem Booleschen Wert). Die Antwort von Starblue deckt es weiter ab.
Vlasec
Nur weil es nicht im Tutorial enthalten ist , heißt das nicht, dass Java es nicht hat - die Tutorials sind nicht (immer) vollständig. Siehe Java-Sprachspezifikation 15.22.2
user85421
5
Es heißt !=, es gibt auch eine logische XNOR namens==
Mark K Cowan

Antworten:

695

Java hat einen logischen XOR-Operator , es ist ^ (wie in a ^ b).

Abgesehen davon können Sie in Java keine neuen Operatoren definieren.

Bearbeiten: Hier ist ein Beispiel:

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);
        }
    }
}

Ausgabe:

false ^ false = false
false ^ true = true
wahr ^ falsch = wahr
wahr ^ wahr = falsch
Javashlook
quelle
5
Dies ist mir auch beim Schreiben meines Beitrags entgangen, aber ich denke, Sie können ^ als logischen Operator (sowie bitweise) verwenden.
Neil Coffey
144
^ ist nicht nur ein bitweiser Operator. Es ist auch ein logischer Operator. Der Operator ^ ist überladen. Es arbeitet mit integralen Typen oder booleschen Typen. +1 für eine tolle Antwort javashlook. Eddie, es wird nicht expliziter als in JLS Abschnitt 15.22.2, "Boolesche logische Operatoren &, ^ und |".
Erickson
97
Und natürlich lautet die Antwort: && und || überspringt die Auswertung des 2. Teils des Ausdrucks und & und | wird immer beide Teile des Ausdrucks auswerten (aus meiner Lektüre von JLS). A ^^ müsste per Definition immer beide Teile bewerten, verhält sich also identisch zu ^. Wahrscheinlich, warum es keine ^^
Eddie
81
@Eddie: Das und ^^ sieht einfach zu sehr nach einem Emoticon aus.
Michael Myers
5
Vielleicht ist es eine Frage der Semantik, aber wenn es um XOR geht, liefern bitweise und logische Ergebnisse das gleiche Ergebnis. Daher sind keine unterschiedlichen Operatoren erforderlich. Die vereinfachte Wahrheitstabelle für einen XOR-Operator lautet X ^! X = 1. Sie können einen Eingang in XOR nicht kurzschließen, da Sie feststellen müssen, ob die Eingänge unterschiedlich sind. Es ist viel einfacher zu verstehen, wenn Sie die Herstellung des tatsächlichen XOR-Gatters kennen.
Hfontanez
305

Ist es nicht x! = Y?

Maurice Perry
quelle
5
Wenn x und y Boolesche Werte sind, sind die Logiktabellen für xor und! = Identisch: t, t => f; t, f => t; f, t => t; f, f => f
Greg Case
81
Maurice: Arrgh du hast mich einfach umgehauen! Wie habe ich das nie bemerkt?
8
@ Milhous Wollen Sie damit sagen, dass a != b != ces nicht funktioniert, aber a ^ b ^ cwird? In diesem Fall liegen Sie falsch .
Fredoverflow
3
Maurice, einfach genial! Es passiert mir, einfache Dinge aus den Augen zu verlieren, wenn es viel zu tun gibt :)
sberezin
6
Diese approch implodiert , wenn beide Seiten Wrapper - Klassen sind, new Boolean(true) != new Boolean(true)gibt true.
Vlastimil Ovčáčík
74

Java hat einen logischen UND-Operator.
Java hat einen logischen ODER-Operator.

Falsch.

Java hat

  • zwei logische UND-Operatoren: normales UND ist & und Kurzschluss UND ist && und
  • zwei logische ODER-Operatoren: normales ODER ist | und Kurzschluss ODER ist ||.

XOR existiert nur als ^, da eine Kurzschlussauswertung nicht möglich ist.

Sternenblau
quelle
2
Interessanter Kommentar. Ist das dokumentiert?
user666412
1
Ich denke & und | sind keine Kurzschlüsse, weil sie bitweise Operatoren sind. Und tatsächlich ist es nicht möglich, sie kurzzuschließen.
Krzysztof Jabłoński
3
@Krzysztof Jabłoński Sie sind bitweise Operatoren für Zahlen, aber hier sprechen wir über boolesche Ausdrücke.
Starblue
3
@ user666412 Ja, in der Java-Sprachspezifikation (wo sonst?).
Starblue
18
Wenn es 2 UND-Operatoren und 2 ODER-Operatoren hat, sind die Anweisungen 'Java hat einen logischen UND-Operator' und 'Java hat einen logischen ODER-Operator' nicht falsch. Per Definition, wenn Sie 2 von etwas haben, dann haben Sie auch 1 davon.
RyanfaeScotland
31

Vielleicht mißverstanden Sie den Unterschied zwischen &und &&, |und || Ziel der Verknüpfung Betreiber &&und|| sind , dass der Wert des ersten Operanden das Ergebnis bestimmen kann und so der zweite Operand nicht ausgewertet werden muss.

Dies ist besonders nützlich, wenn der zweite Operand zu einem Fehler führen würde. z.B

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

Bei XOR müssen Sie jedoch immer den zweiten Operanden auswerten, um das Ergebnis zu erhalten, sodass die einzig sinnvolle Operation ist ^.

Peter Lawrey
quelle
20

Du kannst einfach schreiben (a!=b)

Dies würde genauso funktionieren wie a ^ b.

Shuliyey
quelle
9

Das liegt daran, dass das Überladen von Operatoren bewusst aus der Sprache herausgelassen wurde. Sie "betrogen" ein bisschen mit String-Verkettung, aber darüber hinaus gibt es solche Funktionen nicht.

(Haftungsausschluss: Ich habe noch nicht mit den letzten beiden Hauptversionen von Java gearbeitet. Wenn es jetzt verfügbar ist, bin ich sehr überrascht.)

Kevin Anderson
quelle
5
Beachten Sie, dass Sie auch in C ++ keine neuen Operatoren definieren können. Alles, was Sie tun können, ist, den alten neue Bedeutungen zu geben.
David Thornley
7

Die einzige Operatorüberladung in Java ist + on Strings ( JLS 15.18.1 String Concatenation Operator + ).

Die Community ist seit Jahren in drei Teile geteilt, 1/3 will es nicht, 1/3 will es und 1/3 kümmert sich nicht darum.

Sie können Unicode verwenden, um Methodennamen zu erstellen, die Symbole sind. Wenn Sie also ein Symbol haben, das Sie verwenden möchten, können Sie myVal = x. $ (Y) ausführen. Dabei ist $ das Symbol und x kein Primitiv ... aber das wird in einigen Editoren zweifelhaft und ist einschränkend, da Sie es auf einem Primitiv nicht tun können.

TofuBeer
quelle
7

Folgendes folgt dein Code:

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

ist überflüssig.

Warum nicht schreiben:

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

?

Auch, wie Javashlook sagte , gibt es bereits ^Betreiber.

!=und ^arbeiten identisch * für boolesche Operanden (Ihr Fall), aber anders für ganzzahlige Operanden.

* Hinweise:
1. Sie funktionieren identisch für Operanden boolean(primitiver Typ), jedoch nicht für BooleanOperanden (Objekttyp). As- BooleanWerte (Objekttyp) können einen Wert haben null. Und !=wird zurückkehren falseoder truewenn einer oder beide seiner Operanden sind null, während in diesem Fall ^werfen NullPointerException.
2. Obwohl sie identisch arbeiten, haben sie unterschiedliche Vorrang, z. B. wenn sie verwendet werden mit &: a & b != c & dwerden behandelt als a & (b != c) & d, während a & b ^ c & dbehandelt werden als (a & b) ^ (c & d)(offtopic: autsch, C-artige Vorrangtabelle saugt).

Sasha
quelle
1
Für Boolesche Werte mag ich!=
GKalnytskyi
1
@GKalnytskyi für BooleanWerte !=funktioniert falsch. Für booleanWerte ist es ok.
Vadipp
2
! = und ^ funktionieren für boolesche Operanden nicht identisch . Sie erhalten aufgrund der Priorität unterschiedliche Ergebnisse für "false & false! = True" und "false & false ^ true".
Albert Hendriks
1
@ AlbertHendriks, ich würde besser sagen, dass sie identisch funktionieren , aber unterschiedliche Vorrang haben (obwohl es nur eine Frage der Terminologie ist).
Sasha
6

Hier ist eine var arg XOR-Methode für Java ...

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

Genießen

Timothy Jacobsen
quelle
Das fühlt sich so an, als würde es ein sehr seltsames Verhalten geben. ZB XOR(true,true,true)gibt true zurück, was nicht dem entspricht, was Sie von einer aufgerufenen Methode erwarten würden XOR. Mein erwartetes Verhalten wäre, dass es immer false zurückgibt (was natürlich nicht hilfreich ist)
Richard Tingle
4

Logisches Exklusiv-oder in Java wird aufgerufen !=. Sie können auch verwenden, ^wenn Sie Ihre Freunde verwirren möchten.

Doradus
quelle
2

Sie können Xtend (Infix Operators und Operator Overloading) verwenden, um Operatoren zu überladen und auf Java zu bleiben

iga
quelle
Beachten Sie, dass Sie mit Xtend das Caret nicht überschreiben können ^. Sie müssen verwenden bool_1.xor(bool_2). Merkwürdig ist , dass sich der Parser nicht einmal können Sie verwenden die caret; Sie müssen xorfür Boolesche Werte und bitwiseXorfür Ganzzahlen verwenden. Sie könnten natürlich einen anderen Operator überlasten, aber das würde sehr verwirrend werden.
Kelvin
2

Was Sie verlangen, würde nicht viel Sinn machen. Sofern ich nicht falsch liege, schlagen Sie vor, dass Sie XOR verwenden möchten, um logische Operationen auf die gleiche Weise wie AND und OR auszuführen. Ihr bereitgestellter Code zeigt tatsächlich, worauf ich mich beziehe:

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

Ihre Funktion verfügt über boolesche Eingaben. Wenn bitweises XOR für boolesche Werte verwendet wird, entspricht das Ergebnis dem von Ihnen angegebenen Code. Mit anderen Worten, bitweises XOR ist bereits effizient, wenn einzelne Bits (Boolesche Werte) oder die einzelnen Bits in größeren Werten verglichen werden. Um dies in einen Zusammenhang zu bringen, ist in Bezug auf Binärwerte jeder Wert ungleich Null WAHR und nur NULL ist falsch.

Damit XOR auf die gleiche Weise angewendet wird, wie logisches UND angewendet wird, würden Sie entweder nur Binärwerte mit nur einem Bit verwenden (was das gleiche Ergebnis und die gleiche Effizienz ergibt) oder der Binärwert müsste als Ganzes anstatt pro Bit ausgewertet werden. Mit anderen Worten, der Ausdruck (010 ^^ 110) = FALSE anstelle von (010 ^^ 110) = 100. Dies würde den größten Teil der semantischen Bedeutung aus der Operation entfernen und stellt einen logischen Test dar, den Sie sowieso nicht verwenden sollten.

user2904660
quelle
1

A und B müssten boolesche Werte sein, um! = Dasselbe wie xor zu machen, damit die Wahrheitstabelle gleich aussieht. Sie könnten auch verwenden! (A == B) lol.

John Theibert
quelle
1

Ich benutze die sehr beliebte Klasse "org.apache.commons.lang.BooleanUtils"

Diese Methode wird von vielen Benutzern getestet und ist sicher. Habe Spaß. Verwendungszweck:

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

Da der boolesche Datentyp wie eine Ganzzahl gespeichert wird, funktioniert der Bitoperator ^ wie eine XOR-Operation, wenn er mit booleschen Werten verwendet wird.

//©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
            */
        }
    }
Ledón
quelle
0

Hier ist ein Beispiel:

Geben Sie bei 2 int-Werten true zurück, wenn einer negativ und einer positiv ist. Außer wenn der Parameter "negativ" wahr ist, geben Sie nur dann wahr zurück, wenn beide negativ sind.

    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
quelle
0

Sie müssen zu Scala wechseln, um Ihre eigenen Operatoren zu implementieren

Rohrbeispiel

mut1na
quelle