Kezdő Olvasási idő: ~11 perc

Operátorok

Aritmetikai, logikai, bitenkénti, összehasonlító operátorok és rövidzár kiértékelés

Operátorok és kifejezések

A Java operátorai és kifejezései: aritmetikai, relációs, logikai, bitenkénti, értékadó, ternary, instanceof operátorok, precedencia és kiértékelési sorrend.

1. Definíció

Mi ez?

Az operator egy szimbólum, amely egy vagy több operanduson hajt végre műveletet és eredményt (értéket) produkál. A kifejezés (expression) operátorok és operandusok kombinációja, amely egyetlen értékre értékelődik ki.

Miért fontos?

  • Alapvető építőkő: minden algoritmus, feltétel és ciklus operátorokra épül
  • Teljesítmény: a megfelelő operator választás (pl. bitwise shift vs. szorzás) jelentős különbséget hozhat
  • Olvashatóság: a precedencia és short-circuit kiértékelés megértése elengedhetetlen a hibamentes kódhoz

Hol helyezkedik el?

Az operátorok a Java nyelv szintaktikai alaprétegéhez tartoznak — közvetlenül a típusok és változók fölött, és a vezérlési szerkezetek (control structures) alatt.


2. Alapfogalmak

2.1 Aritmetikai operátorok (Arithmetic operators)

Operator Leírás Példa Eredmény
+ Összeadás 5 + 3 8
- Kivonás 5 - 3 2
* Szorzás 5 * 3 15
/ Osztás 7 / 2 3 (integer division!)
% Maradékos osztás (modulo) 7 % 2 1
++ Inkrementálás i++ / ++i pre/post increment
-- Dekrementálás i-- / --i pre/post decrement

⚠️ Integer division: ha mindkét operandus egész szám, az eredmény is egész (a tizedes rész levágódik).

2.2 Relációs operátorok (Relational / Comparison operators)

Operator Leírás Példa
== Egyenlő a == b
!= Nem egyenlő a != b
> Nagyobb a > b
< Kisebb a < b
>= Nagyobb vagy egyenlő a >= b
<= Kisebb vagy egyenlő a <= b

🔑 Primitíveknél == az értéket hasonlítja össze, objektumoknál a referenciát.

2.3 Logikai operátorok (Logical operators)

Operator Leírás Short-circuit?
&& Logikai ÉS ✅ Igen — ha a bal false, a jobb nem értékelődik ki
|| Logikai VAGY ✅ Igen — ha a bal true, a jobb nem értékelődik ki
! Logikai NEM
& Logikai ÉS (nem short-circuit) ❌ Nem
| Logikai VAGY (nem short-circuit) ❌ Nem

2.4 Bitenkénti operátorok (Bitwise operators)

Operator Leírás Példa
& Bitenkénti ÉS 0b1010 & 0b11000b1000
| Bitenkénti VAGY 0b1010 | 0b11000b1110
^ Bitenkénti XOR 0b1010 ^ 0b11000b0110
~ Bitenkénti NEM (komplemens) ~0b10100b...0101
<< Bal shift (left shift) 1 << 38
>> Jobb shift, előjeles (signed right shift) -8 >> 2-2
>>> Jobb shift, előjel nélküli (unsigned right shift) -1 >>> 2815

2.5 Értékadó operátorok (Assignment operators)

Operator Ekvivalens
= Egyszerű értékadás
+= a = a + b
-= a = a - b
*= a = a * b
/= a = a / b
%= a = a % b
&= a = a & b
|= a = a | b
^= a = a ^ b
<<= a = a << b
>>= a = a >> b
>>>= a = a >>> b

🔑 A compound assignment operátorok (pl. +=) implicit kasztolást tartalmaznak: short s = 1; s += 1; ✅ fordítás OK, de s = s + 1; ❌ compile error (int → short).

2.6 Ternary operator (feltételes kifejezés)

eredmeny = (feltétel) ? értékHaTrue : értékHaFalse;

Ez az egyetlen háromoperandusú (ternary) operator a Java-ban.

2.7 instanceof operator

if (obj instanceof String s) {   // pattern matching (Java 16+)
    System.out.println(s.length());
}
  • null instanceof Bármi → mindig false
  • Java 16+ óta pattern matching: deklarálhat változót az instanceof-on belül

2.8 Precedencia tábla (Operator Precedence)

Prioritás Operátor(ok) Asszociativitás
1 (legmagasabb) () [] . Balról jobbra
2 ++ -- (postfix) Balról jobbra
3 ++ -- (prefix) + - (unáris) ~ ! Jobbról balra
4 (type) cast Jobbról balra
5 * / % Balról jobbra
6 + - Balról jobbra
7 << >> >>> Balról jobbra
8 < <= > >= instanceof Balról jobbra
9 == != Balról jobbra
10 & Balról jobbra
11 ^ Balról jobbra
12 | Balról jobbra
13 && Balról jobbra
14 || Balról jobbra
15 ? : Jobbról balra
16 (legalacsonyabb) = += -= stb. Jobbról balra

3. Gyakorlati használat

Mikor melyik operátort használjuk?

Feladat Ajánlott Miért?
Páros/páratlan vizsgálat n % 2 == 0 Egyszerű, olvasható
2 hatványával szorzás/osztás n << 1 / n >> 1 Teljesítmény (bár a JIT amúgy is optimalizál)
Null-safe ellenőrzés obj != null && obj.method() Short-circuit megvéd a NullPointerException-tól
Egyszerű if-else érték Ternary ? : Tömörebb, de ne ágyazd egymásba!
Flag-ek kezelése Bitwise &, |, ^ Memória-hatékony, gyors
Típusellenőrzés instanceof + pattern matching Java 16+ modern idiom

4. Kód példák

4.1 Alapszintű példák

// Integer division — gyakori meglepetés
int a = 7 / 2;        // 3, NEM 3.5!
double b = 7.0 / 2;   // 3.5 — legalább az egyik operandus double

// Pre vs. post increment
int i = 5;
int x = i++;  // x = 5, i = 6 (post: először értékadás, aztán növelés)
int y = ++i;  // y = 7, i = 7 (pre: először növelés, aztán értékadás)

// Modulo negatív számoknál
int mod = -7 % 3;  // -1 (az eredmény előjele az osztandó előjelét követi)

4.2 Short-circuit evaluation

// ✅ Helyes: short-circuit megvéd a NullPointerException-tól
String name = null;
if (name != null && name.length() > 0) {
    System.out.println(name);
}

// ❌ Hibás: & nem short-circuit, NullPointerException lesz!
if (name != null & name.length() > 0) {  // 💥 NPE!
    System.out.println(name);
}

4.3 Bitwise flag kezelés

// Flag-ek definiálása
static final int READ    = 0b0001;  // 1
static final int WRITE   = 0b0010;  // 2
static final int EXECUTE = 0b0100;  // 4

// Flag beállítása
int permissions = READ | WRITE;          // 0b0011 = 3

// Flag ellenőrzése
boolean canRead = (permissions & READ) != 0;   // true

// Flag törlése
permissions = permissions & ~WRITE;             // 0b0001 = 1

// Flag váltása (toggle)
permissions = permissions ^ EXECUTE;            // 0b0101 = 5

4.4 Ternary — jó és rossz használat

// ✅ Egyszerű, olvasható
String status = (age >= 18) ? "felnőtt" : "kiskorú";

// ❌ Egymásba ágyazott ternary — olvashatatlan!
String category = (age < 13) ? "gyerek" : (age < 18) ? "tinédzser" : "felnőtt";

// ✅ Helyette if-else vagy switch
String category;
if (age < 13) category = "gyerek";
else if (age < 18) category = "tinédzser";
else category = "felnőtt";

4.5 Compound assignment implicit cast

short s = 10;
// s = s + 1;   // ❌ Compile error! (s + 1 = int, int → short szűkítő)
s += 1;         // ✅ OK! A += implicit kasztolást tartalmaz: s = (short)(s + 1)

byte b = 127;
b += 1;         // ✅ Fordul, DE overflow! b = -128

5. Trade-offok

Szempont Opció A Opció B Mikor melyik?
Olvashatóság vs. tömörség if-else Ternary ? : Ternary egyszeri egyszerű választáshoz; if-else komplexebb logikához
Bitwise vs. hagyományos n * 2 n << 1 Modern JVM-en nincs érdemi sebességkülönbség; n * 2 olvashatóbb
Short-circuit vs. eager && / || & / | Szinte mindig short-circuit; eager csak ha mindkét oldali mellékhatás kell
== vs. equals() == .equals() == primitívekhez és referencia-összehasonlításhoz; .equals() tartalom-összehasonlításhoz

6. Gyakori hibák

❌ 6.1 Integer division meglepetés

double result = 1 / 3;          // 0.0, nem 0.333!
double correct = 1.0 / 3;       // 0.333...  ✅
double alsoCorrect = (double) 1 / 3;  // 0.333...  ✅

❌ 6.2 Precedencia hiba

// Szándék: (a & b) != 0
if (a & b != 0) { }   // ❌ Valójában: a & (b != 0) — a != megelőzi a &-t!
if ((a & b) != 0) { }  // ✅ Zárójelezés!

❌ 6.3 == vs. equals objektumoknál

String s1 = new String("hello");
String s2 = new String("hello");
s1 == s2;        // false — különböző referenciák!
s1.equals(s2);   // true  ✅

❌ 6.4 Pre/post increment mellékhatás

int i = 0;
int result = i++ + ++i;  // ❌ Zavaros, platform-specifikusnak tűnhet
// Java-ban jól definiált (result = 0 + 2 = 2), de KERÜLENDŐ!

❌ 6.5 Overflow compound assignment-nél

byte b = 127;
b += 1;     // -128! Nincs compile-time warning, silent overflow

7. Senior szintű meglátások

7.1 Operator overloading hiánya

A Java — a C++-szal és a Kotlin-nal ellentétben — nem támogatja az operator overloading-ot. Egyetlen kivétel a + operator, amely a String concatenation-höz belső kezelést kap (a compiler StringBuilder-re vagy invokedynamic-ra írja át Java 9+).

7.2 Kifejezések kiértékelési sorrendje (JLS §15.7)

A Java Language Specification garantálja, hogy az operandusok balról jobbra értékelődnek ki (left-to-right evaluation). Ez nem azonos a precedenciával:

int i = 0;
int r = (i = 1) + (i = 2);  // r = 1 + 2 = 3, NEM 2 + 2!
// A bal operandus előbb értékelődik ki, mint a jobb

7.3 Numeric promotion szabályok

  • Ha bármelyik operandus double → az eredmény double
  • Különben, ha bármelyik float → eredmény float
  • Különben, ha bármelyik long → eredmény long
  • Különben: mindkettő int-re promótálódik (akkor is, ha byte + byte!)
byte a = 10, b = 20;
// byte c = a + b;  // ❌ Compile error! a + b = int
int c = a + b;      // ✅

7.4 NaN és Infinity viselkedés

double nan = Double.NaN;
nan == nan;           // false! NaN soha nem egyenlő önmagával
Double.isNaN(nan);    // true  ✅

double inf = 1.0 / 0; // Infinity, nem ArithmeticException!
int zero = 1 / 0;     // 💥 ArithmeticException (integer division)

7.5 Switch expression vs. ternary (Java 14+)

// Java 14+ switch expression — olvashatóbb, mint az egymásba ágyazott ternary
String type = switch (code) {
    case 1 -> "admin";
    case 2 -> "user";
    default -> "guest";
};

8. Szószedet

Fogalom Jelentés
Operator Szimbólum, amely operandus(ok)on műveletet hajt végre
Operand Az az érték, amelyen az operator dolgozik
Expression Operátorok és operandusok kombinációja, amely értékre értékelődik ki
Precedence Operátorok kiértékelési sorrendjének prioritása
Associativity Ha azonos a precedencia, a kiértékelés iránya (balról/jobbról)
Short-circuit evaluation Logikai kifejezés rövidített kiértékelése (a jobb oldal nem fut le, ha az eredmény már eldőlt)
Bitwise Bitekre vonatkozó művelet
Ternary operator Háromoperandusú feltételes kifejezés (? :)
Numeric promotion Kisebb típusok automatikus konverziója nagyobb típusra műveletnél
Compound assignment Összetett értékadás (+=, -=, stb.), implicit kasztolással
instanceof Típusellenőrző operator, Java 16+ óta pattern matching támogatással
Unary operator Egyoperandusú operátor (pl. !, ~, ++)
Binary operator Kétoperandusú operátor (pl. +, &&)

9. Gyorsreferencia

  • Integer division: 7 / 2 = 3 — használj 7.0 / 2-t vagy explicit cast-ot ha tizedest akarsz
  • Short-circuit: && és || → a jobb oldalt nem értékeli ki, ha az eredmény már eldőlt
  • Precedencia: ha kétely merül fel, zárójelezz(a & b) != 0
  • == vs. equals: == primitívekhez, .equals() objektumokhoz
  • Compound assignment: += implicit cast-ot tartalmaz → s += 1 fordul, s = s + 1 nem (ha s short/byte)
  • Numeric promotion: byte + byte = int → explicit cast kell a visszaadáshoz
  • NaN: Double.NaN != Double.NaN → használj Double.isNaN()-t
  • instanceof null: null instanceof Bármi → mindig false
  • Bitwise shift: 1 << n = 2ⁿ — hasznos flag-ekhez és hatványokhoz
  • Ternary: max 1 szint mélyen — ha bonyolultabb, használj if-else-t vagy switch expression-t
  • Evaluation order: JLS garantálja a balról-jobbra kiértékelést, de ne építs rá mellékhatásokkal!
  • Operator overloading: Java-ban nincs — kivéve a + String concatenation-höz

🎮 Játékok

8 kérdés