Tõeväärtused ja loogikatehted
Sissejuhatus
Tõeväärtus (boolean) on primitiivne andmetüüp, millel saab olla vaid kaks väärtust: tõene (true) ja väär (false).
See on põhiline andmetüüp loogiliste väidete ja tingimuste esitamiseks programmis.
Väärtustamine
Kõige lihtsam viis on omistada otse kas true või false väärtus:
boolean a = true;
boolean b = false;
Võrdlused annavad ka tulemuseks kas true või false:
int age = 20;
boolean isAdult = age >= 18; // true
boolean isTeenager = age < 20; // false
boolean isExactly20 = age == 20; // true
Sellest tulenevalt võib ka tingimusi kokku aheldada, et tekitada keerukam avaldis:
int temperature = 5;
boolean isWetAndCold = temperature > 0 && temperature < 10; // returns true if temperature is between 0 and 10
Ahvatlev oleks kirjutada näiteks boolean a = 10 < x < 20, et näha, kas x on 10 ja 20 vahel.
Sedasi töötab arvude võrdlemine näiteks Pythonis, kuid Javas see aga ei tööta, sest iga < operaator saab ainult korraga kontrollida kahte väärtust.
Õige on kirjutada boolean a = 10 < x && x < 20
Põhioperatsioonid
Loogikatehete jaoks on Javas kolm operaatorit:
| Operaator | Nimi | Kirjeldus | Näide |
|---|---|---|---|
&& | JA (AND) | Tõene, kui mõlemad pooled on tõesed | true && true on true |
|| | VÕI (OR) | Tõene, kui vähemalt üks pool on tõene | true || false on true |
! | EI (NOT) | Pöörab väärtuse vastupidiseks | !true on false |
Vastav tõeväärtustabel:
| P | Q | P && Q | P || Q | !P |
|---|---|---|---|---|
true | true | true | true | false |
true | false | false | true | false |
false | true | false | true | true |
false | false | false | false | true |
Näited:
boolean hasTicket = true;
boolean hasID = false;
// AND - Both sides have to be true
boolean canEnter = hasTicket && hasID;
System.out.println(canEnter); // false
// OR - At least one side has to be true
boolean hasDocuments = hasTicket || hasID;
System.out.println(hasDocuments); // true
// NOT - inverts value
boolean needsTicket = !hasTicket;
System.out.println(needsTicket); // false
Loogikatehete järjekord
Loogikatehete puhul kasutatakse short-circuit evaluation meetodit ehk järgnev avaldis valideeritakse siis, kui esimene seda lubab.
&& operaatori puhul tähendab see seda, et kui eelnev tingimus on väär, siis järgmist tööle ei panda:
boolean result = false && someExpensiveMethod();
// someExpensiveMethod is never executed because the statement before it is false
See tuleb kasuks näiteks olukorras, kus mingil muutujaga on vaja läbi viia mingi tegevus, kuid selle väärtus võib parasjagu ka null olla:
String text = null;
// Correct - text.length() is not executed because text != null resulted in false
if (text != null && text.length() > 0) {
System.out.println("Text is not empty");
}
// Error - null does not have .length() method
if (text.length() > 0 && text != null) {
System.out.println("Text is not empty");
}
|| puhul on vastupidi.
Kui eelmisega oli, et false puhul ei panda järgnevaid tööle, siis ||-iga ei panda järgnevaid tööle, kui eelneva tulemus on true.
boolean result = true || someExpensiveMethod();
// someExpensiveMethod() is never executed because the statement before it is true
See tuleb kasuks olukorras, kus näiteks üks tingimus peaks trumpama teist üle:
int age = 25;
// If user is an admin then don't impose age verification
if (isAdmin || age >= 18) {
// ...
}
short-circuit evaluation käitumist on võimalik vältida, kui kasutada topelt märkide asemel ühekordseid (& ja |).
Sel juhul mõlemad operandide pooled käivitatakse.
Praktikas kasutatakse loogiliste avaldiste puhul peaaegu alati && ja ||, kuna need on ohutumad, selgemad ning väldivad tarbetuid arvutusi ja võimalikke vigu.
Stiilireeglid
Tõeväärtustega tegeledes kehtivad ka teatud stiilireeglid.
Esmalt, tingimuslauses tõeväärtusi kontrollides vältige true või false-ga võrdlemist:
// Bad style, avoid writing like this
if (isStudent == true) {
System.out.println("Is a student");
}
if (hasLicense == false) {
System.out.println("No license");
}
// Correct style
if (isStudent) {
System.out.println("Is a student");
}
if (!hasLicense) {
System.out.println("No license");
}
Sarnane reegel kehtib ka meetodite puhul, mis tagastavad tõeväärtust.
Loogikaavaldiste juhul ei pea eraldi true või false tagastama:
// Bad style, explicitly returning true or false
public boolean isEven(int number) {
if (number % 2 == 0) {
return true;
} else {
return false;
}
}
// Correct style - == evaluates to true or false anyways
public boolean isEven(int number) {
return number % 2 == 0;
}
Tõeväärtuste nimetused peaksid olema küsimused, millele saab vastata jaatavalt või eitavalt. Näiteks:
- isActive, hasPermission, canEdit
- isEmpty, isValid, isComplete
- shouldRetry, willExpire, needsUpdate
Boolean wrapper klass
Nagu teiste primitiivsete tüüpide puhul, on ka boolean jaoks olemas seda tähistav klass - Boolean.
Wrapper klassidest on pikemalt juttu siin, seega siinkohal keskendutakse ainult Boolean klassi spetsiifikale.
Praktikas kasutatakse seda ainult juhtudel, kus ei ole võimalik primitiive kasutada (nt. kollektsioonid) või null-väärtust on vaja võimalik kasutada.
Antud olukorras rakenduvad ka teadaolevad riskid, näiteks NullPointerException-i oht.
Boolean klass võimaldab kasutada ka parseBoolean meetodit ehk sõne tõeväärtuseks teisendamine:
boolean b1 = Boolean.parseBoolean("true"); // true
boolean b2 = Boolean.parseBoolean("TRUE"); // true (case-insensitive)
boolean b3 = Boolean.parseBoolean("false"); // false
boolean b4 = Boolean.parseBoolean("yes"); // false (only "true" gives true!)