Szintaxis és alap típusok
Primitív típusok, wrapper osztályok, változók, scope, életciklus és típuskonverzió
Szintaxis és alap típusok
A Java nyelv alapkövei: primitív típusok, wrapper osztályok, változók, hatókör, életciklus és típuskonverzió.
1. Definíció
Mi ez?
A Java egy erősen típusos (strongly typed) nyelv, ami azt jelenti, hogy minden változónak deklarálni kell a típusát (vagy a var kulcsszóval ki kell következtetnie a fordítónak). A nyelv alapjait a primitív típusok és az azokat becsomagoló wrapper osztályok adják.
Miért létezik?
- Típusbiztonság: a fordító compile-time elkapja a típushibákat
- Teljesítmény: a primitív típusok közvetlenül a stack-en tárolódnak, nem kell heap allokáció
- Platformfüggetlenség: a típusok mérete rögzített minden platformon (pl.
intmindig 32 bit)
Hol helyezkedik el?
Ez a Java nyelv legalapvetőbb szintje — minden más (OOP, Collections, Streams) erre épül.
2. Alapfogalmak
2.1 Primitív típusok
A Java 8 primitív típust tartalmaz:
| Típus | Méret | Alapértelmezett | Tartomány | Felhasználás |
|---|---|---|---|---|
byte |
8 bit | 0 |
-128 — 127 | Memória-takarékos tömbök, I/O |
short |
16 bit | 0 |
-32 768 — 32 767 | Ritkán használt |
int |
32 bit | 0 |
-2³¹ — 2³¹-1 | Alapértelmezett egész típus |
long |
64 bit | 0L |
-2⁶³ — 2⁶³-1 | Nagy számok, timestamp |
float |
32 bit | 0.0f |
~±3.4×10³⁸ | Ritkán, inkább double |
double |
64 bit | 0.0d |
~±1.7×10³⁰⁸ | Alapértelmezett tizedes típus |
char |
16 bit | '\u0000' |
0 — 65 535 | Unicode karakter |
boolean |
~1 bit* | false |
true/false |
Logikai érték |
*A
booleanmérete implementáció-függő: a JVM általábanint-ként (32 bit) tárolja a stack-en.
Fontos szabályok:
- Primitívek nem lehetnek
null - Primitívek nem használhatók generics-ben (
List<int>❌,List<Integer>✅) - Az
intliterálok alapértelmezetteninttípusúak, a tizedes literálokdoubletípusúak
2.2 Wrapper osztályok
Minden primitívnek van egy megfelelő wrapper osztálya:
| Primitív | Wrapper | Cache tartomány |
|---|---|---|
byte |
Byte |
-128 — 127 (teljes) |
short |
Short |
-128 — 127 |
int |
Integer |
-128 — 127 |
long |
Long |
-128 — 127 |
float |
Float |
nincs cache |
double |
Double |
nincs cache |
char |
Character |
0 — 127 |
boolean |
Boolean |
TRUE / FALSE (mindkettő) |
Autoboxing/Unboxing:
Integer x = 42; // autoboxing: int → Integer
int y = x; // unboxing: Integer → int
Integer z = null;
int w = z; // ⚠️ NullPointerException!
Integer Cache (-128 — 127):
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true (cache-ből jön)
Integer c = 128;
Integer d = 128;
System.out.println(c == d); // false (új objektumok!)
System.out.println(c.equals(d)); // true (érték összehasonlítás)
2.3 Változók, scope, lifecycle
Változó típusok:
| Típus | Deklaráció helye | Alapértelmezett | Élettartam |
|---|---|---|---|
| Lokális változó | Metóduson belül | ❌ Nincs (kötelező inicializálni) | Blokk vége |
| Instance változó | Osztályban (nem static) | ✅ Van | Objektum GC-ig |
| Class változó | static |
✅ Van | Program vége |
| Paraméter | Metódus szignatúra | Hívó adja | Metódus vége |
Scope szabályok:
public void example() {
int x = 10; // scope: egész metódus
if (x > 5) {
int y = 20; // scope: csak ez az if blokk
System.out.println(x + y); // OK
}
// System.out.println(y); // ❌ Compile error! y itt nem látható
}
2.4 Type casting
Implicit (widening) — automatikus, veszteségmentes:
byte → short → int → long → float → double
char → int
Explicit (narrowing) — kézi, adatvesztes lehet:
double d = 9.78;
int i = (int) d; // i = 9 (csonkítás, NEM kerekítés!)
int big = 130;
byte b = (byte) big; // b = -126 (overflow!)
Speciális szabályok:
floatésdoubleközötti konverzió precíziós veszteséggel járhatint→floatkonverziónál is lehet veszteség (float csak 24 bit mantissza)
3. Gyakorlati használat
Mikor mit használj?
| Szituáció | Ajánlás | Miért |
|---|---|---|
| Egész számok általában | int |
Alapértelmezett, leggyakoribb |
| Pénzügyi számítások | BigDecimal ⚠️ |
NEM double! Pontossági hibák! |
| Kollekcióban szám | Integer (wrapper) |
Generics követelmény |
| Nagy adathalmaz, memória fontos | primitív tömbök | Wrapper 16+ byte/elem overhead |
| Boolean flag | boolean primitív |
Egyszerű, nincs null-kérdés |
| Nullable boolean (DB-ből) | Boolean wrapper |
null = "nem tudjuk" |
Mikor NE használd?
- ❌
double-t pénzügyi kalkulációra —0.1 + 0.2 != 0.3 - ❌
==-t wrapper összehasonlításra — cache határon kívül hibás - ❌
float-ot, ha nem szükséges —doublea default,floatritka
4. Kód példák
Alap példa — Típusok és konverzió
public class TypeBasics {
public static void main(String[] args) {
// Primitívek
int count = 42;
double price = 19.99;
boolean active = true;
char grade = 'A';
// Widening (automatikus)
long bigCount = count; // int → long, OK
double bigPrice = count; // int → double, OK
// Narrowing (explicit cast szükséges)
int rounded = (int) price; // 19 (csonkítás!)
byte small = (byte) count; // 42 (belefér)
// Wrapper autoboxing
Integer boxed = count; // autoboxing
int unboxed = boxed; // unboxing
// var (Java 10+) — a típust a fordító következteti ki
var name = "Alice"; // String
var number = 42; // int (NEM Integer!)
var list = List.of(1, 2, 3); // List<Integer>
}
}
Haladó példa — Pénzügyi kalkuláció hibája
public class MoneyPitfall {
public static void main(String[] args) {
// ❌ ROSSZ: double pontossági hiba
double price = 0.1;
double quantity = 3;
System.out.println(price * quantity);
// Output: 0.30000000000000004 (!)
// ✅ HELYES: BigDecimal használata
BigDecimal bdPrice = new BigDecimal("0.1");
BigDecimal bdQuantity = new BigDecimal("3");
System.out.println(bdPrice.multiply(bdQuantity));
// Output: 0.3
}
}
Gyakori csapda — Integer cache
public class IntegerCacheTrap {
public static void main(String[] args) {
// Cache-en belül (-128..127): MŰKÖDIK
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true ✅
// Cache-en kívül: NEM MŰKÖDIK
Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false ❌
System.out.println(c.equals(d)); // true ✅
// ⚠️ Null unboxing
Integer nullable = null;
// int value = nullable; // NullPointerException!
}
}
5. Trade-offok
| Szempont | Primitív | Wrapper |
|---|---|---|
| ⚡ Teljesítmény | Gyors (stack, nincs allokáció) | Lassabb (heap allokáció, GC) |
| 💾 Memória | Minimális (pl. int = 4 byte) |
Jelentős (pl. Integer = ~16 byte) |
| 🔧 Karbantarthatóság | Egyszerű, de nem lehet null | Null-kezelés kell, de kifejezőbb |
| 🔄 Rugalmasság | Nem használható generics-ben | Kollekcióban és generics-ben használható |
Konkrét számok:
int[1000]→ ~4 KB memóriaInteger[1000]→ ~20 KB memória (5x több!)- Egy millió
Integerautoboxing → jelentős GC nyomás
6. Gyakori hibák
1. `==` használata wrapper-eknél
// ❌ Hibás
if (value1 == value2) { ... } // referencia összehasonlítás!
// ✅ Helyes
if (value1.equals(value2)) { ... }
// vagy
if (Objects.equals(value1, value2)) { ... } // null-safe
2. `double` használata pénzügyi számításokra
// ❌ Soha ne csinálj ilyet
double balance = 1000.00;
balance -= 999.99;
// balance = 0.010000000000047748 (NEM 0.01!)
// ✅ BigDecimal-t használj
BigDecimal balance = new BigDecimal("1000.00");
balance = balance.subtract(new BigDecimal("999.99"));
// balance = 0.01 ✅
3. Null unboxing
// ❌ NullPointerException dobódik
Integer count = getCountFromDb(); // null-t adhat vissza
int total = count + 1; // NPE!
// ✅ Null check
int total = (count != null) ? count + 1 : 1;
// vagy Optional használat
int total = Optional.ofNullable(count).orElse(0) + 1;
4. Narrowing cast overflow
// ❌ Csendesen hibás eredmény
int big = 128;
byte b = (byte) big; // b = -128 (overflow, nincs exception!)
// ✅ Ellenőrzés cast előtt
if (big >= Byte.MIN_VALUE && big <= Byte.MAX_VALUE) {
byte b = (byte) big;
} else {
throw new ArithmeticException("Value out of byte range");
}
// vagy Java 8+:
byte b = Math.toIntExact(big); // ArithmeticException overflow-nál
7. Senior szintű meglátások
Mikor számít a primitív vs wrapper választás?
- Hot path-on (pl. tight loop, valós idejű feldolgozás): mindig primitív. Autoboxing egy milliós ciklusban mérhető lassulást okoz.
- Domain modellben: wrapper, ha az érték nullable (pl.
Integer age— "nem tudjuk az életkorát" vsint age— "0 éves"). - API tervezésnél:
Optional<Integer>jobb, mint nullableInteger.
Integer cache testreszabás
A JVM -XX:AutoBoxCacheMax=<size> flag-gel bővítheti az Integer cache tartományt. Nagyfrekvenciás rendszerekben (pl. ID-k 1-10000 között) ez javíthat a teljesítményen.
`var` használat — mikor igen, mikor ne?
// ✅ Jó: a jobb oldal egyértelművé teszi a típust
var users = new ArrayList<User>();
var response = httpClient.send(request, BodyHandlers.ofString());
// ❌ Rossz: a típus nem egyértelmű
var result = process(); // mi a típusa?
var x = flag ? getA() : getB(); // melyik típus?
JIT optimalizáció
A JIT fordító sok esetben escape analysis segítségével kioptimalizálja az autoboxing-ot, ha a wrapper objektum nem "szökik ki" a metódusból. De erre nem szabad építeni — production kódban mérj!
Floating point összehasonlítás
// ❌ Soha ne használj == -t double-nél
double a = 0.1 + 0.2;
if (a == 0.3) { ... } // false!
// ✅ Epsilon-alapú összehasonlítás
private static final double EPSILON = 1e-10;
if (Math.abs(a - 0.3) < EPSILON) { ... } // true
8. Szószedet
| Kifejezés | Definíció |
|---|---|
| Autoboxing | Primitív típus automatikus konverziója wrapper osztállyá (int → Integer) |
| Unboxing | Wrapper osztály automatikus konverziója primitívvé (Integer → int) |
| Widening | Implicit típuskonverzió kisebb típusból nagyobba (veszteségmentes) |
| Narrowing | Explicit típuskonverzió nagyobb típusból kisebbe (adatvesztes lehet) |
| Integer Cache | A JVM -128 és 127 közötti Integer objektumokat cache-eli az Integer.valueOf() híváskor |
| Stack | Memóriaterület ahol a lokális primitív változók és referenciák tárolódnak |
| String Pool | → Lásd: String kezelés |
| Escape Analysis | JIT technika: megállapítja, hogy egy objektum "kiszökik-e" a metódusból |
9. Gyorsreferencia
- 🔢 8 primitív típus:
byte,short,int,long,float,double,char,boolean - 📦 Wrapper = primitív + null + generics kompatibilitás (de drágább)
- ⚠️
==wrapper-eknél referenciát hasonlít,.equals()kell! - 💰 Pénzhez MINDIG
BigDecimal, sohadouble - 🎯 Integer cache: -128 — 127 (bővíthető JVM flag-gel)
- 📏 Widening automatikus, narrowing explicit cast kell
- 🚫 Null unboxing = NPE — mindig ellenőrizd!
- 🔍
var(Java 10+) — csak ha a típus egyértelmű a kontextusból - ⚡ Hot path = primitív, domain model = wrapper ha nullable kell
- 🧮
float≈ 7 tizedes jegy,double≈ 15 tizedes jegy precizitás
🎮 Játékok
8 kérdés