Maneira mais limpa de alternar uma variável booleana em Java?

211

Existe uma maneira melhor de negar um booleano em Java do que um simples if-else?

if (theBoolean) {
    theBoolean = false;
} else {
    theBoolean = true;
}
Kevin Griffin
fonte
oh legal, eu estava prestes a fazer a mesma pergunta, embora minha pergunta fosse específica para javascript / as3 ou ECMAScript em geral, suponho ... o que será facilmente abordado por essa pergunta.
Matt lohkamp
E se não houver! operador ??
precisa saber é o seguinte

Respostas:

537
theBoolean = !theBoolean;
Aaron Maenpaa
fonte
16
Isso é ... realmente óbvio - opa! Não sei por que não pensei nisso. Obrigado.
Kevin Griffin
Booleano parece uma escolha natural - talvez no futuro.
Matt lohkamp
21
@ypnos: !!bool == !(!(bool)) == bool.
Christoffer Hammarström
12
@ ChristofferHammarström Por essa lógica, então --integer == - (- (número inteiro)) == número inteiro?
user515655
1
@ user515655 - A linguagem define um --operador (na verdade, dois deles, juntamente com dois ++operadores), mas não define um !!operador. Se desejar, -(-(integer))use espaço em branco entre os dois -caracteres. Mas !!analisa como dois !operadores, independentemente do espaço em branco.
Ted Hopp
164
theBoolean ^= true;

Menos pressionamentos de tecla se a sua variável tiver mais de quatro letras

Editar : o código tende a retornar resultados úteis quando usado como termos de pesquisa do Google. O código acima não. Para quem precisa, é um XOR bit a bit, conforme descrito aqui .

pateksan
fonte
14
e está de acordo com DRY :)
teta
6
A brevidade é a alma da inteligência.
22468 Paul Brinkley
7
agora eu tenho o XOR de drop-name (drop de sintaxe?) de maneira informal para parecer legal na frente dos meus amigos programadores. Sua resposta deve ser mesclada com a escolhida, juntas são pura perfeição.
Matt lohkamp
6
@ScottStanchfield Essas pessoas devem aprender. Não é nada difícil, não é um hack, e não saber que muitas vezes leva a códigos ruins, como por exemplo o que esta pergunta. Esta é uma verdadeira explosão - cinco linhas usando as convenções padrão!
Maaartinus
4
Esta operação também é 12% mais rápida do que outras versões como theBoolean = !theBoolean;outheBoolean = theBoolean ? false : true;
Blaine Kasten
32

Existem vários

O caminho "óbvio" (para a maioria das pessoas)

theBoolean = !theBoolean;

O caminho "mais curto" (na maioria das vezes)

theBoolean ^= true;

A maneira "mais visual" (mais incerta)

theBoolean = theBoolean ? false : true;

Extra: alternar e usar em uma chamada de método

theMethod( theBoolean ^= true );

Como o operador de atribuição sempre retorna o que foi atribuído, isso alternará o valor por meio do operador bit a bit e retornará o novo valor atribuído a ser usado na chamada do método.

Levita
fonte
Envolva a implementação em uma função / método chamado de alternância e, em seguida, quase não há como confundi-la.
Lambage 8/09/17
@ Reiner: CDefinitivamente, mas Javanão é permitido misturar booleano e inteiro (também coisas como while(1)não são possíveis em Java).
Levite
@ Linguagem: Verdade, mas o lado negativo é que você não pode alternar um booleano simplesmente passando, pois não é possível passar primitivos por referência em Java. Você precisaria reatribuir o resultado do método à sua variável ou criar uma classe de wrapper para o booleano.
Levite
A "maneira óbvia" acima é sinalizada pelo SONAR com - Atribuições internas devem ser evitadas.
Orby
2

Se você usa valores nulos booleanos e os considera falsos, tente o seguinte:

static public boolean toggle(Boolean aBoolean) {
    if (aBoolean == null) return true;
    else return !aBoolean;
}

Se você não estiver entregando valores nulos booleanos, tente o seguinte:

static public boolean toggle(boolean aBoolean) {
   return !aBoolean;
}

Estes são os mais limpos, porque mostram a intenção na assinatura do método, são mais fáceis de ler em comparação com o ! operador e pode ser facilmente depurado.

Uso

boolean bTrue = true
boolean bFalse = false
boolean bNull = null

toggle(bTrue) // == false
toggle(bFalse) // == true
toggle(bNull) // == true

Obviamente, se você usar o Groovy ou um idioma que permita métodos de extensão, poderá registrar uma extensão e simplesmente:

Boolean b = false
b = b.toggle() // == true
Steven Spungin
fonte
Boa abordagem, mas não totalmente inequívoca (imho). Para alguém que usa / lê apenas "alternar (..)" pode pensar, chamar o método (sem atribuí-lo novamente à variável) já pode alternar a variável subjacente. É óbvio para nós agora ver o código, mas na vida real pode ser bastante difícil de depurar. Um nome de método melhor pode ser "oposto" ou possivelmente "negação", para tornar isso um pouco mais óbvio; ou use a primeira abordagem com um objeto Booleane realmente o alterne dentro do método (mas ainda um pouco ambíguo).
Levite
2

Esta resposta surgiu ao pesquisar "função booleana invertida java". O exemplo abaixo evitará que certas ferramentas de análise estática falhem nas construções devido à lógica de ramificação. Isso é útil se você precisar inverter um booleano e não tiver construído testes de unidade abrangentes;)

Boolean.valueOf(aBool).equals(false)

ou alternativamente:

Boolean.FALSE.equals(aBool)

ou

Boolean.FALSE::equals
Parâmetro médico
fonte
1
I como o fato de que você poderia passar Boolean.FALSE::equalspara uma função de mapeamento em vez de escrever um pouco lambda
Patrick Parker
0

Se você não está fazendo nada particularmente profissional, sempre pode usar uma classe Util. Ex, uma classe util de um projeto para uma classe.

public class Util {


public Util() {}
public boolean flip(boolean bool) { return !bool; }
public void sop(String str) { System.out.println(str); }

}

então basta criar um objeto Util Util u = new Util(); e ter algo para o retornoSystem.out.println( u.flip(bool) );

Se você vai acabar usando a mesma coisa várias vezes, use um método, e especialmente se houver projetos, faça uma classe Util. Não sei qual é o padrão da indústria. (Programadores experientes ficam à vontade para me corrigir)

Will D.
fonte
0

A classe BooleanUtilssuporta a negação de um booleano. Você encontra esta classe em commons-lang: commons-lang

BooleanUtils.negate(theBoolean)
Alex
fonte
-4

Antes:

boolean result = isresult();
if (result) {
    result = false;
} else {
    result = true;
}

Depois de:

boolean result = isresult();
result ^= true;
Nikhil Kumar
fonte
Quem já votou? Você também pode explicar a razão?
Nikhil Kumar
11
Duas razões principais para pensar por que alguém pode ter votado contra você: 1) Necromancia do segmento ( vamos lá! A pergunta foi feita há 7 (!) Anos atrás! ) E sua resposta não traz nada de novo à mesa; 2) O eleitor esperava algo "mais limpo" ( leia-se: mais curto ) - a resposta de AaronMaenpaa é um excelente exemplo disso.
Priidu Neemre
5
@ Elltz: Pelo contrário - eu realmente votei nele, já que a resposta era tecnicamente correta. No entanto, devo dizer que não gosto da tendência de contrabandear respostas de usuários anteriores por carma barato (consulte a resposta do nlaq).
Priidu Neemre
@PriiduNeemre, pergunta feita e resposta aceita antes de 7 anos ou mais e você acha que, exceto na lista, alguém dará voto positivo? Além disso, sua resposta também não está correta. :(
user1140237 11/11
2
depois: resultado booleano =! isresult ();
Petter Friberg