Operátory, výrazy

Tomáš Pitner, upravil Marek Šabo
tomp@fi.muni.cz

Operátor

  • "Znaménko operace", pokyn pro vykonání operace při vyhodnocení výrazu.
  • V Javě mají operátory napevno daný význam, nelze je přetěžovat jako v C++.
  • Operátor dle počtu parametrů (argumentů) bývá

    • unární (např. minus),
    • binární (např. děleno) nebo
    • ternární (podmíněný výraz).

  • Každý operátor má určen typ svých argumentů nebo
  • může být polymorfní, aplikovatelný na různé typy.

Výraz

  • Syntakticky správný řetězec operandů a operátorů s případnými závorkami
  • Operandy jsou:

    • literály (přímo zadané hodnoty, třeba 1.23),
    • proměnné nebo
    • funkční volání.

  • Výraz lze při splnění dalších podmínek vyhodnotit (spočítat) a získat výsledek.

Aritmetické

  • Binární (dvouparametrové) aritmetické operátory: + - * / % (zbytek po celočíselném dělení)
  • Operátor dělení / je polymorfní

    • funguje pro celočíselné argumenty (byte, short, int a long) jako celočíselný
    • pro floating-point (float, double) jako obyčejné dělení.

  • Na to je třeba dávat pozor — i když dvě (fakticky i typově) celá čísla nejsou dělitelná, jako podíl se nám vrátí vždy celé číslo (typově i hodnotově).
  • Abychom dosáhli desetinného výsledku, musí být aspoň jeden z operandů typově s pohyblivou řádovou čárkou.
  • Lze zařídit např. typovou konverzí ((double)a)/b pro celočíselné proměnné a, b
  • nebo použitím literálu neceločíselného typu, např. double d = 1.0/i

Logické

  • Pracují nad logickými (booleovskými) hodnotami,
  • vč. výsledků relačních operací (porovnávání) <, >, == , apod.

Logické — součiny

Logické součiny (AND)
  • & nepodmíněný součin, vždy se vyhodnotí oba operandy,
  • && podmíněný součin, líné vyhodnocování (lazy evaluation) — druhý operand se vyhodnotí, jen nelze-li o výsledku součinu rozhodnout z hodnoty prvního

Logické — součty, negace

Logické součty (OR)
  • | nepodmíněný součet, vždy se vyhodnotí oba operandy,
  • || podmíněný součet, líné vyhodnocování — druhý operand se vyhodnotí, jen nelze-li o výsledku rozhodnout z hodnoty prvního
Negace (NOT)
  • ! vrátí znegovanou logickou hodnotu argumentu

Relační (porovnávací)

Uspořádání

<, , >=, > lze použít na porovnávání primitivních číselných a znakových hodnot

Rovnost

==, != test na rovnost/nerovnost lze navíc použít na porovnávání primitivních hodnot i objektů

Porovnávání objektů

  • Pozor na porovnávání objektů.
  • Operátor == vrací true jen při rovnosti odkazů, tj. jsou-li objekty identické.
  • Rovnost obsahu (tedy "rovnocennost") objektů se zjišťuje voláním metody o1.equals(o2).
  • equals se může podívat "dovnitř" objektů, je-li tak napsaná.
  • Aby to takto fungovalo, musíme ji my sami u našich vlastních typů překrýt (=sami napsat).
  • Blíže viz Porovnávání objektů

Porovnávání floating-point čísel

  • Pozor na srovnávání floating-point čísel na rovnost.
  • Je třeba počítat s chybami zaokrouhlení.
  • Místo porovnání na přesnou rovnost raději používejme jistou toleranci.
  • abs(expected-actual) < delta

Bitové operace

  • bitový součin &
  • bitový součet |
  • bitový exkluzivní součet (XOR) (znak "stříška") ^
  • bitová negace (bitwise-NOT) (znak "tilda") ~ obrátí bity argumentu a výsledek vrátí

Bitové posuny

  • vlevo << o stanovený počet bitů
  • vpravo >> o stanovený počet bitů s respektováním znaménka
  • vpravo >>> o stanovený počet bitů bez respektování znaménka

Operátor podmíněného výrazu ? :

Formát: booleovskýVýraz ? hodnotaKdyžPlatí : hodnotaKdyžNeplatí

Příklad: x < 0 ? 0 : x (vrátí x pokud je nezáporné, jinak 0)

  • Jediný ternární operátor v Javě, navíc polymorfní.
  • Pracuje nad různými typy 2. a 3. argumentu.
  • Platí-li první operand (má hodnotu true),

    • je výsledkem hodnota druhého operandu
    • jinak je výsledkem hodnota třetího operandu

  • Typ prvního operandu musí být boolean, typy druhého a třetího musí být přiřaditelné do výsledku.

Operátory typové konverze (přetypování)

  • Píše se (typ)hodnota , např. (Person)o, kde o byla proměnná deklarovaná jako Object.
  • Pro objektové typy se ve skutečnosti nejedná o žádnou konverzi spojenou se změnou obsahu objektu, nýbrž pouze o potvrzení (běhovou typovou kontrolu), že běhový typ objektu je ten požadovaný — např. (viz výše) že o je typu Person.
  • Naproti tomu u primitivních typů se jedná o skutečný převod, tzn. úpravu hodnoty — např. int přetypujeme na short a ořeže se tím rozsah.

Operátor zřetězení +

  • Plus je rovněž polymorfním operátorem.
  • Chová se jinak pro čísla — sčítá a jinak pro řetězce, kde spojuje.
  • Výsledkem je vždy řetězec, ale argumenty mohou být i jiných typů,

    int i = 1;
    System.out.println("variable i = " + i);

  • Tento kód je v pořádku, s řetězcovou konstantou se spojí řetězcová podoba dalších argumentů (např. čísla).
  • Pokud je argumentem zřetězení odkaz na objekt o:

    • je-li o == null : použije se řetězec null
    • je-li o != null : použije se hodnota vrácená metodou o.toString(), kterou lze překrýt a dosáhnout tak očekávaného řetězcového výstupu

Priority operátorů a vytváření výrazů

  • Motto: Pravidla priorit operátorů je dobré znát, ale ještě lepší je závorkovat, aby nedošlo k chybám a každý to přesně pochopil!
  • nejvyšší prioritu má násobení, dělení, nejnižší přiřazení
  • nízkou prioritu má ternární operátor booleovskýVýraz ? výrazProTrue : výrazProFalse

Pozn. Rozhodně NEZNEUŽÍVEJME přiřazení ve smyslu, že jej současně použijeme jako výraz, tzn. pracujeme s jeho hodnotu! Že to vůbec jde, je spíše reziduum převzaté do Javy z C.

/