Najczystszy sposób przełączania zmiennej boolean w Javie?


211

Czy istnieje lepszy sposób na zanegowanie wartości logicznej w Javie niż zwykły if-else?

if (theBoolean) {
    theBoolean = false;
} else {
    theBoolean = true;
}

och, miło, miałem właśnie zadać to samo pytanie, chociaż moje pytanie dotyczyłoby javascript / as3 lub ogólnie ECMAScript, jak sądzę ... które z łatwością można ująć w to pytanie.
— matt lohkamp

Co jeśli nie ma! operator?
— onmyway133

Odpowiedzi:


537
theBoolean = !theBoolean;

16
To ... naprawdę oczywiste - ups! Nie wiem, dlaczego o tym nie pomyślałem. Dzięki.
— Kevin Griffin

! Boolean wydaje się naturalnym wyborem - może w przyszłości.
— matt lohkamp

21
@ypnos: !!bool == !(!(bool)) == bool.
— Christoffer Hammarström

12
@ ChristofferHammarström Zgodnie z tą logiką nie powinno --integer == - (- (liczba całkowita)) == liczba całkowita?
— user515655,

1
@ user515655 - Język definiuje --operatora (w rzeczywistości dwóch z nich wraz z dwoma ++operatorami), ale nie definiuje !!operatora. Jeśli chcesz -(-(integer)), możesz użyć spacji między dwoma -znakami. Ale !!parsuje jako dwa !operatory niezależnie od białych znaków.
— Ted Hopp

164
theBoolean ^= true;

Mniej naciśnięć klawiszy, jeśli zmienna ma więcej niż cztery litery

Edycja : kod zwykle zwraca przydatne wyniki, gdy jest używany jako wyszukiwane hasło Google. Powyższy kod nie. Dla tych, którzy go potrzebują, jest to bitowy XOR, jak opisano tutaj .


14
i jest zgodny z DRY :)
— Tetha

6
Zwięzłość jest duszą dowcipu.
— Paul Brinkley

7
teraz przechodzę do XOR-up-name-drop-drop-syntax-drop ?, żeby wyglądać fajnie przed moimi programistami. Twoja odpowiedź powinna zostać połączona z wybraną, razem są czystą doskonałością.
— matt lohkamp

6
@ScottStanchfield Tacy ludzie powinni się tego nauczyć. To wcale nie jest trudne, nie jest hackowaniem, a nie wiedząc, że często prowadzi do gównianego kodu, jak np. To pytanie. To jest prawdziwy wysadzenie - pięć linii przy użyciu standardowych konwencji!
— maaartinus

4
Ta operacja jest również o 12% szybsza niż w innych wersjach, takich jak theBoolean = !theBoolean;lubtheBoolean = theBoolean ? false : true;
— Blaine Kasten

32

Istnieje kilka

„Oczywisty” sposób (dla większości osób)

theBoolean = !theBoolean;

„Najkrótsza” droga (przez większość czasu)

theBoolean ^= true;

„Najbardziej wizualny” sposób (najbardziej niepewny)

theBoolean = theBoolean ? false : true;

Dodatkowo: Przełącz i używaj w wywołaniu metody

theMethod( theBoolean ^= true );

Ponieważ operator przypisania zawsze zwraca to, co zostało przypisane, spowoduje to przełączenie wartości za pomocą operatora bitowego, a następnie zwróci nowo przypisaną wartość do użycia w wywołaniu metody.


Zawiń implementację w funkcję / metodę o nazwie toggle, a wtedy prawie nie ma sposobu, aby ją pomylić.
— Lambage

@ Reeiner: Na Cpewno, ale w Javanim nie wolno mieszać wartości logicznych i całkowitych (również takie rzeczy while(1)nie są możliwe w Javie).
— Lewita

@Lambage: To prawda, ale z drugiej strony nie można przełączać wartości logicznej, po prostu przekazując ją, ponieważ nie można przekazywać prymitywów przez referencję w Javie. Trzeba będzie ponownie przypisać wynik metody do zmiennej lub w inny sposób utworzyć klasę opakowania dla wartości logicznej.
— Lewita

„Oczywisty sposób” powyżej został oznaczony przez SONAR przy pomocy - Należy unikać przypisań wewnętrznych.
— Orby

2

Jeśli używasz boolowskich wartości NULL i uznajesz je za fałszywe, spróbuj tego:

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

Jeśli nie przekazujesz boolowskich wartości NULL, spróbuj tego:

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

Są to najczystsze, ponieważ pokazują intencję w metodzie, są łatwiejsze do odczytania w porównaniu do ! operatora i można go łatwo debugować.

Stosowanie

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

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

Oczywiście, jeśli używasz Groovy lub języka, który pozwala na metody rozszerzeń, możesz zarejestrować rozszerzenie i po prostu zrobić:

Boolean b = false
b = b.toggle() // == true

Dobre podejście, ale nie całkowicie jednoznaczne (imho). Dla kogoś, kto używa / czyta tylko „przełącznik (..)”, może pomyśleć, wywołanie metody (bez przypisywania jej ponownie do zmiennej) może już przełączyć zmienną bazową. Teraz jest dla nas oczywiste, że widzimy kod, ale w prawdziwym życiu może być dość trudny do debugowania. Lepszą nazwą metody może być „przeciwieństwo” lub ewentualnie „negacja”, aby uczynić to nieco bardziej oczywistym; lub użyj pierwszego podejścia z obiektem Booleani naprawdę przełącz go w ramach metody (ale nadal nieco niejednoznacznej).
— Lewita

2

Ta odpowiedź pojawiła się podczas wyszukiwania „jaolowej inwertowanej funkcji boolean”. Poniższy przykład zapobiegnie niepowodzeniom niektórych narzędzi analizy statycznej z powodu logiki rozgałęziania. Jest to przydatne, jeśli trzeba odwrócić wartość logiczną i nie opracowano kompleksowych testów jednostkowych;)

Boolean.valueOf(aBool).equals(false)

lub alternatywnie:

Boolean.FALSE.equals(aBool)

lub

Boolean.FALSE::equals

1
Podoba mi się to, że można przejść Boolean.FALSE::equalsdo funkcji mapowania zamiast pisać małą lambda
— Patrick Parker

0

Jeśli nie robisz nic szczególnie profesjonalnego, zawsze możesz skorzystać z klasy Util. Ex, klasa util z projektu dla klasy.

public class Util {


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

}

następnie po prostu utwórz obiekt Util Util u = new Util(); i coś do zwrotuSystem.out.println( u.flip(bool) );

Jeśli będziesz używać tej samej metody w kółko, użyj metody, a zwłaszcza, jeśli dotyczy to różnych projektów, stwórz klasę Util. Nie wiem jednak, jaki jest standard branżowy. (Doświadczeni programiści mogą mnie poprawić)



-4

Przed:

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

Po:

boolean result = isresult();
result ^= true;

Kto kiedykolwiek przegłosował? Czy możesz również wyjaśnić powód?
— Nikhil Kumar

11
Dwa główne powody, dla których mogę wymyślić, dlaczego ktoś cię ocenił: 1) Nekromancja wątku ( daj spokój ! Pytanie zostało zadane 7 (!) Lat temu! ) I twoja odpowiedź nie wnosi nic nowego do stołu; 2) Wyborca ​​oczekiwał czegoś „czystszego” ( czytaj: krótszy ) - odpowiedź AaronaMaenpaa jest tego najlepszym przykładem.
— Priidu Neemre

5
@Elltz: Wręcz przeciwnie - głosowałem go, ponieważ odpowiedź była technicznie poprawna. Muszę jednak powiedzieć, że nie podoba mi się trend polegający na tym, że bootlegging odpowiedzi poprzednich użytkowników na tanią karmę (patrz odpowiedź nlaq).
— Priidu Neemre

@PriiduNeemre, pytanie zadane i odpowiedź zaakceptowane przed 7+ latami i czy uważasz, że poza listą ktoś da głos? poza tym twoja odpowiedź również nie jest do znaku .. :(
— user1140237

2
after: wynik boolowski =! isresult ();
— Petter Friberg,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.