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 & 0b1100 → 0b1000 |
| |
Bitenkénti VAGY | 0b1010 | 0b1100 → 0b1110 |
^ |
Bitenkénti XOR | 0b1010 ^ 0b1100 → 0b0110 |
~ |
Bitenkénti NEM (komplemens) | ~0b1010 → 0b...0101 |
<< |
Bal shift (left shift) | 1 << 3 → 8 |
>> |
Jobb shift, előjeles (signed right shift) | -8 >> 2 → -2 |
>>> |
Jobb shift, előjel nélküli (unsigned right shift) | -1 >>> 28 → 15 |
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, des = 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→ mindigfalse- 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énydouble - Különben, ha bármelyik
float→ eredményfloat - Különben, ha bármelyik
long→ eredménylong - Különben: mindkettő
int-re promótálódik (akkor is, habyte+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álj7.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 += 1fordul,s = s + 1nem (hasshort/byte) - Numeric promotion:
byte + byte = int→ explicit cast kell a visszaadáshoz - NaN:
Double.NaN != Double.NaN→ használjDouble.isNaN()-t - instanceof null:
null instanceof Bármi→ mindigfalse - 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