Do czego służą operatory
Operatory to symbole, które łączą wartości, żeby obliczyć nowe. Używasz ich już intuicyjnie: + dodaje, > porównuje. Java dzieli je na kilka rodzin: arytmetyczne, porównania, logiczne, przypisania i kilka specjalnych, jak inkrementacja i operator trójargumentowy.
Większość operatorów przyjmuje dwie wartości (jedną przed symbolem, drugą po nim) i zwraca wynik. Sztuka polega na tym, by wiedzieć, jakiego typu jest wynik i w jakiej kolejności operatory są stosowane. Właśnie tu potykają się początkujący.
Operatory arytmetyczne
Pięć operatorów arytmetycznych działa na liczbach: +, -, *, / i % (reszta z dzielenia).
Operator % to reszta z dzielenia: 17 % 5 to 2, bo 5 mieści się w 17 trzy razy i zostaje 2. To codzienne narzędzie do sprawdzania podzielności: n % 2 == 0 to standardowy test "czy n jest parzyste?".
Zwróć też uwagę, że + ma dwie role: z liczbami dodaje, ale gdy po którejś stronie jest String, łączy tekst.
Pierwsza linia jest czytana od lewej do prawej: "Total: " + 3 to już napis, więc 4 jest doklejane jako tekst. Otocz obliczenie nawiasami, jeśli chcesz, żeby wykonało się najpierw.
Pułapka dzielenia całkowitego
To najczęstsza niespodzianka. Gdy oba operandy / są liczbami całkowitymi, Java wykonuje dzielenie całkowite i odrzuca część ułamkową: nie zaokrągla, tylko obcina w stronę zera.
Aby dostać wynik dziesiętny, przynajmniej jeden operand musi być double: zapisz go z .0 albo zrzutuj jedną stronę przez (double). Rzutowanie (double)(5 / 2) nie pomaga, bo dzielenie całkowite 5 / 2 wykonało się już przed rzutowaniem; rzutować trzeba operand, a nie wynik.
Operatory porównania
Operatory porównania zadają pytanie tak/nie i zwracają boolean. Jest ich sześć: ==, !=, <, >, <=, >=.
Uważaj na różnicę między = (przypisanie: "wstaw tu tę wartość") a == (porównanie: "czy są równe?"). Pomylenie ich to klasyczny błąd.
Ważne zastrzeżenie: == porównuje referencje obiektów, a nie ich zawartość. Dla napisów używaj .equals().
Używaj == dla typów prostych, takich jak int i boolean, a .equals() zawsze wtedy, gdy porównujesz zawartość obiektów, np. napisów.
Operatory logiczne
Operatory logiczne łączą wartości logiczne: && (i), || (lub) i ! (nie). Tak wyrażasz warunki w rodzaju "jest pełnoletni i ma bilet".
&& i || stosują obliczanie skrócone (short-circuit): Java przestaje obliczać, gdy tylko odpowiedź jest pewna. Przy &&, jeśli lewa strona to false, prawa nigdy nie jest sprawdzana; przy ||, jeśli lewa strona to true, prawa jest pomijana. To nie tylko optymalizacja, można na tym polegać dla bezpieczeństwa:
if (text != null && text.length() > 0) { ... }
Jeśli text to null, lewa strona daje false, a text.length() nigdy nie jest wywoływane, co pozwala uniknąć NullPointerException. Po odwróceniu kolejności program by się wysypał.
Przypisanie i inkrementacja
= przypisuje, ale Java ma też przypisania złożone, które łączą działanie z przypisaniem: +=, -=, *=, /=, %=. A ++ / -- dodają lub odejmują jeden.
++ występuje w dwóch odmianach: postfiksowej (count++), która zwraca starą wartość, a potem zwiększa, i prefiksowej (++count), która najpierw zwiększa, a potem zwraca nową wartość. Różnica ma znaczenie tylko wtedy, gdy używasz wyniku w tym samym wyrażeniu:
Gdy ++ stoi w osobnej linii, forma postfiksowa i prefiksowa nie różnią się niczym, więc wybierz tę, która czyta się jaśniej, i nie wciskaj inkrementacji w większe wyrażenia.
Operator trójargumentowy
Operator trójargumentowy condition ? a : b to zwięzły if/else, który daje wartość: jeśli warunek jest true, wynikiem jest a, w przeciwnym razie b.
Świetnie sprawdza się w krótkich przypisaniach typu albo/albo. Nie zagnieżdżaj operatorów trójargumentowych w sobie: szybko robi się to nieczytelne, a zwykły if/else jest jaśniejszy.
Priorytet i nawiasy
Operatory działają w ustalonej kolejności, podobnie jak w matematyce: *, /, % wiążą mocniej niż + i -, te mocniej niż porównania, porównania mocniej niż &&, a na końcu jest ||.
Nie musisz uczyć się całej tabeli na pamięć. Gdy wyrażenie miesza rodziny operatorów albo musisz się zatrzymać, żeby ustalić kolejność, dodaj nawiasy: nic nie kosztują, a następnemu czytelnikowi od razu pokazują intencję.
Dalej: rzutowanie typów
Kilka pułapek z tej strony, jak dzielenie całkowite czy mieszanie int i double, sprowadza się do typów. Świadoma zamiana między typami liczbowymi to rzutowanie i o nim jest następna strona.
Najczęściej zadawane pytania
Co robi operator % w Javie?
% to operator reszty z dzielenia (modulo): daje to, co zostaje po dzieleniu całkowitym. 7 % 3 to 1, a 10 % 2 to 0. To standardowy sposób na sprawdzenie podzielności (n % 2 == 0 oznacza, że n jest parzyste) i na zawinięcie wartości w zakres.
Dlaczego 5 / 2 daje w Javie 2, a nie 2.5?
Gdy oba operandy są liczbami całkowitymi, / wykonuje dzielenie całkowite i odrzuca część ułamkową, więc 5 / 2 to 2, a nie 2.5. Aby dostać 2.5, przynajmniej jeden operand musi być typu double: napisz 5.0 / 2, 5 / 2.0 albo zrzutuj jedną stronę przez (double) 5 / 2.
Czym różni się == od equals() w Javie?
== porównuje typy proste według wartości, ale dla obiektów (w tym String) porównuje referencje, czyli sprawdza, czy to ten sam obiekt w pamięci. Aby porównać zawartość obiektów, użyj .equals(). Porównanie dwóch napisów przez == może zwrócić false nawet przy identycznym tekście, więc dla napisów zawsze używaj "a".equals(b).