Criando um operador "lógico exclusivo ou" em Java

274

Observações:

Java possui um operador AND lógico.
Java possui um operador OR lógico.
Java possui um operador NOT lógico.

Problema:

Java não possui um operador XOR lógico, de acordo com a sun . Eu gostaria de definir um.

Definição do método:

Como método, é simplesmente definido da seguinte forma:

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


Chamada de método:

Este método é chamado da seguinte maneira:

boolean myVal = logicalXOR(x, y);


Uso do Operador:

Eu preferiria ter um operador, usado da seguinte maneira:

boolean myVal = x ^^ y;


Questão:

Não consigo encontrar nada sobre como definir um novo operador em Java. Por onde devo começar?

onze81
fonte
1
que? o link que você forneceu tem o conteúdo 'OR bit a bit exclusivo'
Mathew P. Jones
você estava se perguntando então se você poderia definir operadores em Java como você pode em C ++?
Avgvstvs
1
Parece que você não entendeu a diferença entre & e &&. Ambos são operadores lógicos (em um booleano). A resposta da Starblue cobre mais amplamente.
Vlasec 04/08/19
só porque não está no tutorial , não significa que o Java não o possua - os tutoriais não estão (sempre) completos. Veja a especificação da linguagem Java 15.22.2
user85421
5
É chamado !=, há também uma XNOR lógica chamada==
Mark K Cowan

Respostas:

695

Java tem um operador XOR lógico , é ^ (como em a ^ b).

Além disso, você não pode definir novos operadores em Java.

Edit: Aqui está um exemplo:

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

Resultado:

false ^ false = false
false ^ true = true
verdadeiro ^ falso = verdadeiro
verdadeiro ^ verdadeiro = falso
javashlook
fonte
5
Isso também escapou da minha memória quando escrevi minha postagem, mas acho que você PODE usar ^ como um operador lógico (bem como bit a bit).
911 Neil Coffey
144
^ não é apenas um operador bit a bit. É também um operador lógico. O operador ^ está sobrecarregado. Opera em tipos integrais ou booleanos. +1 para uma ótima resposta javashlook. Eddie, não fica mais explícito que a Seção 15.22.2 da JLS, "Operadores lógicos booleanos &, ^ e |".
21715
97
E, claro, a resposta é que && e || pulará a avaliação da 2ª parte da expressão e & e | sempre avaliará as duas partes da expressão (da minha leitura do JLS). Um ^ ^ sempre teria que avaliar as duas partes, por definição, de modo que se comporte de forma idêntica a ^. Provavelmente porque não há nenhum ^^
Eddie
81
@ Eddie: Isso e ^^ parecem muito com um emoticon.
Michael Myers
5
Talvez seja uma questão de semântica, mas quando se trata de XOR, bit a bit e lógica produzem o mesmo resultado. Portanto, não há necessidade de operadores distintos. A tabela verdade simplificada para um operador XOR é X ^! X = 1. Você não pode causar um curto-circuito em uma entrada no XOR porque precisa determinar se as entradas são diferentes. É muito mais fácil entender se você conhece a fabricação do portão XOR real.
precisa saber é o seguinte
305

Não é x! = Y?

Maurice Perry
fonte
5
Se xey são booleanos, a tabela lógica para xor e! = É idêntica: t, t => f; t, f => t; f, t => t; f, f => f
Greg Case
81
Maurice: Arrgh, você acabou de me surpreender! Como eu nunca percebi isso?
8
@Milhous Você está dizendo a != b != cque não vai funcionar, mas a ^ b ^ cvai? Nesse caso, você está errado .
Fredoverflow
3
Maurice, simplesmente brilhante! Acontece-me a perder coisas simples da vista quando não há muito a fazer :)
sberezin
6
Essa abordagem implode quando os dois lados são classes de invólucro, new Boolean(true) != new Boolean(true)true.
Vlastimil Ovčáčík
74

Java possui um operador AND lógico.
Java possui um operador OR lógico.

Errado.

Java tem

  • dois operadores AND lógicos: AND normal é & e curto-circuito AND é &&, e
  • dois operadores OR lógicos: OR normal é | e curto-circuito OU é ||.

O XOR existe apenas como ^, porque a avaliação de curto-circuito não é possível.

starblue
fonte
2
Comentário interessante. Isso está documentado?
user666412
1
Eu acho que ee | não são um curto-circuito porque são operadores bit a bit. E, de fato, não é possível causar um curto-circuito.
Krzysztof Jabłoński
3
@Krzysztof Jabłoński Eles são operadores bit a bit em números, mas aqui estamos falando sobre expressões booleanas.
Starblue 14/05
3
@ user666412 Sim, na Especificação de Linguagem Java (onde mais?).
Starblue 14/05
18
Se houver 2 operadores AND e 2 operadores OR, as instruções 'Java possui um operador AND lógico' e 'Java possui um operador OR lógico' não estão erradas. Por definição, se você tem 2 de algo, também tem 1.
RyanfaeScotland
31

Talvez você tenha entendido mal a diferença entre &and &&, |e || O objetivo dos operadores de atalho &&e ||é que o valor do primeiro operando possa determinar o resultado e, portanto, o segundo operando não precise ser avaliado.

Isso é especialmente útil se o segundo operando resultar em um erro. por exemplo

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

No entanto, com o XOR , você sempre deve avaliar o segundo operando para obter o resultado, portanto a única operação significativa é ^.

Peter Lawrey
fonte
20

Você pode escrever (a!=b)

Isso funcionaria da mesma maneira que a ^ b.

Shuliyey
fonte
9

Isso ocorre porque a sobrecarga do operador é algo que eles especificamente deixaram deliberadamente fora do idioma. Eles "trapacearam" um pouco com a concatenação de strings, mas além disso, essa funcionalidade não existe.

(aviso de isenção de responsabilidade: não trabalhei com os últimos dois grandes lançamentos de java, por isso, se estiver disponível agora, ficarei muito surpreso)

Kevin Anderson
fonte
5
Lembre-se de que você também não pode definir novos operadores em C ++. Tudo o que você pode fazer é dar novos significados aos antigos.
23715 David Thornley
7

O único operador que sobrecarrega em Java é + em Strings ( JLS 15.18.1 String Concatenation Operator + ).

A comunidade foi dividida em três por anos, 1/3 não o quer, 1/3 o quer e 1/3 não se importa.

Você pode usar o unicode para criar nomes de métodos que são símbolos ... portanto, se você tiver um símbolo que deseja usar, poderá fazer myVal = x. $ (Y); onde $ é o símbolo ex não é um primitivo ... mas isso vai ser desonesto em alguns editores e é limitado, pois você não pode fazer isso em um primitivo.

TofuBeer
fonte
7

A seguir, seu código:

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

é supérfluo.

Por que não escrever:

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

?

Além disso, como javashlook disse , já existe ^operador.

!=e ^trabalhe de forma idêntica * para operandos booleanos (seu caso), mas de maneira diferente para operandos inteiros.

* Notas:
1. Eles funcionam de forma idêntica para operandos boolean(tipo primitivo), mas não Boolean(tipo de objeto). Os Booleanvalores (tipo de objeto) podem ter valor null. E !=retornará falseou truequando um ou ambos os seus operandos estiverem null, enquanto ^lançará NullPointerExceptionneste caso.
2. Embora funcionem de forma idêntica, eles têm precedência diferente, por exemplo, quando usados ​​com &: a & b != c & dserão tratados como a & (b != c) & d, enquanto a & b ^ c & dserão tratados como (a & b) ^ (c & d)(offtopic: ai, tabela de precedência no estilo C é uma porcaria).

Sasha
fonte
1
Para valores booleanos que eu gosto!=
GKalnytskyi
1
@GKalnytskyi for Booleanvalues !=funciona incorretamente. Para booleanvalores está tudo bem.
vadipp
2
! = e ^ não funcionam de forma idêntica para operandos booleanos. Você obterá resultados diferentes para "falso e falso! = Verdadeiro" versus "falso e falso ^ verdadeiro" por causa da precedência.
Albert Hendriks
1
@AlbertHendriks, é melhor dizer que eles funcionam de forma idêntica, mas têm precedência diferente (embora seja apenas uma questão de terminologia).
Sasha
6

Aqui está um método XOR var arg para java ...

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

Aproveitar

Timothy Jacobsen
fonte
Parece que vai ter um comportamento muito estranho. Por exemplo, XOR(true,true,true)retorna true, o que parece não ser o que você esperaria de um método chamado XOR. Meu comportamento esperado seria que ele sempre retorna falso (que é, naturalmente, não é útil)
Richard Tingle
5

Exclusivo lógico - ou em Java é chamado !=. Você também pode usar ^se quiser confundir seus amigos.

Doradus
fonte
2

Você pode usar o Xtend (operadores infix e sobrecarga de operadores) para sobrecarregar os operadores e 'permanecer' em Java

iga
fonte
Observe que o Xtend não permite que você substitua o cursor ^; você deve usar bool_1.xor(bool_2). Estranhamente, o analisador nem permite que você use o cursor; você deve usar xorpara booleanos e bitwiseXorpara números inteiros. É claro que você poderia sobrecarregar outro operador, mas isso seria muito confuso.
Kelvin
2

O que você está pedindo não faria muito sentido. A menos que eu esteja incorreto, você está sugerindo que deseja usar o XOR para executar operações lógicas da mesma forma que AND e OR. Seu código fornecido realmente mostra o que estou me referindo:

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

Sua função possui entradas booleanas e, quando o XOR bit a bit é usado em booleanos, o resultado é o mesmo que o código que você forneceu. Em outras palavras, o XOR bit a bit já é eficiente na comparação de bits individuais (booleanos) ou na comparação de bits individuais em valores maiores. Para colocar isso em contexto, em termos de valores binários, qualquer valor diferente de zero é TRUE e apenas ZERO é falso.

Portanto, para que o XOR seja aplicado da mesma forma que Logical AND é aplicado, você usaria apenas valores binários com apenas um bit (fornecendo o mesmo resultado e eficiência) ou o valor binário teria que ser avaliado como um todo, em vez de por bit. Em outras palavras, a expressão (010 ^^ 110) = FALSE em vez de (010 ^^ 110) = 100. Isso removeria a maior parte do significado semântico da operação e representa um teste lógico que você não deve usar de qualquer maneira.

user2904660
fonte
1

A e B teriam que ser valores booleanos para fazer! = O mesmo que xor, para que a tabela verdade tivesse a mesma aparência. Você também pode usar! (A == B) lol.

John Theibert
fonte
1

Estou usando a classe muito popular "org.apache.commons.lang.BooleanUtils"

Este método é testado por muitos usuários e seguro. Diverta-se. Uso:

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

Como o tipo de dados booleano é armazenado como um número inteiro, o operador de bit ^ funciona como uma operação XOR se usado com valores booleanos.

//©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
fonte
0

Aqui está um exemplo:

Dados 2 valores int, retorne true se um for negativo e outro for positivo. Exceto se o parâmetro "negativo" for verdadeiro, retorne verdadeiro somente se ambos forem negativos.

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

você precisará mudar para o Scala para implementar seus próprios operadores

exemplo de tubo

mut1na
fonte