3. Változók

A BasicsDemo program összeadja 1-től 10-ig az egész számokat, majd kiírja az eredményt.

public class BasicsDemo {
    public static void main(String[] args) {
        int sum = 0;
        for (int current = 1; current <= 10; current++) {
            sum += current;
        }
        System.out.println("Sum = " + sum);
    }
}

A program a következőt írja ki:

Sum = 55

Ez a kis program használja az alapvető nyelvi elemeket: változókat, operátorokat és vezérlési szerkezeteket.

Az objektum az állapotát változókban tárolja.

A változó olyan adatelem, amely azonosítóval van ellátva.

Egy változó nevét és típusát egyértelműen meg kell adni a programunkban, ha használni akarjuk azt. A változó neve csak érvényes azonosító lehet: tetszőleges hosszúságú Unicode karakterekből álló sorozat, de az első helyen csak betű szerepelhet. A változó típusa meghatározza, hogy milyen értékeket vehet fel a változó, és milyen műveleteket hajthatunk végre rajta. A változó nevét és típusát a változódeklarációban adjuk meg, ami általában ehhez hasonló:

type name;

A változó rendelkezik hatókörrel (érvényességi tartománnyal) is. A hatáskört a változódeklaráció helye egyértelműen meghatározza.

Az alábbi példa különböző változók deklarációját mutatja:

public class MaxVariablesDemo {
    public static void main(String args[]) {
        byte largestByte = Byte.MAX_VALUE;
        short largestShort = Short.MAX_VALUE;
        int largestInteger = Integer.MAX_VALUE;
        long largestLong = Long.MAX_VALUE;
        float largestFloat = Float.MAX_VALUE;
        double largestDouble = Double.MAX_VALUE;
        char aChar = 'S';
        boolean aBoolean = true;
        System.out.println("The largest byte value is " + largestByte);
        System.out.println("The largest short value is " + largestShort);
        System.out.println("The largest integer value is " + largestInteger);
        System.out.println("The largest long value is " + largestLong);
        System.out.println("The largest float value is " + largestFloat);
        System.out.println("The largest double value is " + largestDouble);
        if (Character.isUpperCase(aChar)) {
            System.out.println("The character " + aChar + " is upper case.");
        } else {
            System.out.println("The character " + aChar + " is lower case.");
        }
        System.out.println("The value of aBoolean is " + aBoolean);
    }
}

A program kimenete:

The largest byte value is 127
The largest short value is 32767
The largest integer value is 2147483647
The largest long value is 9223372036854775807
The largest float value is 3.40282e+38
The largest double value is 1.79769e+308
The character S is upper case.
The value of aBoolean is true

3.1. Adattípusok

Minden változó rendelkezik adattípussal. A változó adattípusa határozza meg, hogy milyen értékeket vehet fel a változó, és milyen műveletek végezhetők vele. A MaxVariablesDemo példaprogramban az

int largestInteger;

deklarál egy largestInteger nevű változót int adattípussal. Az int típus csak egész számot tud tárolni.

A Java nyelvben az adattípusoknak két csoportja van: primitív és referencia típusok. A primitív adattípusok egy egyszerű értéket képesek tárolni: számot, karaktert vagy logikai értéket. A változó neve közvetlenül egy értéket jelent.

A következő táblázatok az összes primitív típust tartalmazzák. A példaprogramunk minden típusból deklarál egyet.

Egészek

Típus Leírás Méret/formátum
byte bájt méretű egész 8-bit kettes komplemens
short rövid egész 16-bit kettes komplemens
int egész 32-bit kettes komplemens
long hosszú egész 64-bit kettes komplemens

Valós számok

Típus Leírás Méret/formátum
float gyszeres pontosságú lebegőpontos 32-bit IEEE 754
double dupla pontosságú lebegőpontos 64-bit IEEE 754

Egyéb típusok

Típus Leírás Méret/formátum
char karakter 16-bit Unicode karakter
boolean logikai érték true vagy false

Lehetőségünk van egyből kezdőértéket is adni a változónknak:

int anInt = 4;

A tömbök, az osztályok és az interfészek referencia-típusúak. A referencia-változó más nyelvek mutató vagy memóriacím fogalmára hasonlít. Az objektum neve (objectName) nem egy közvetlen értéket, hanem csak egy referenciát jelent.

Referencia működése

Az értéket közvetetten, a referencián keresztül érhetjük el.

3.2. Változó nevek

A program változónevekkel azonosítja a változóértékeket.

A Java nyelvben a következők érvényesek a nevekre:

  • Valódi azonosító legyen, tetszőlegesen hosszú Unicode karaktersorozat, de az első karakter csak betű lehet.
  • Nem lehet foglalt szó, logikai literál (true vagy false) vagy null.
  • Egyedinek kell lenni az érvényességi tartományban, viszont más tartománybeli változóval megegyezhet.

Konvenció (tehát nem kötelező, de szokás), hogy a változóneveket kisbetűvel kezdjük, az osztályneveket pedig naggyal. Ha a név több szóból áll össze, a közbülső szavak kezdőbetűit mindig naggyal írjuk. A többszavas nevek ragasztására más nyelvekben használt _ karakter Javában nem használatos.

3.3. Érvényességi tartomány

A változó érvényességi tartománya a programnak az a területe, ahol a változó használható egyszerű névként. Ezen kívül meghatározza, hogy a rendszer mikor foglal le és szabadít fel memóriát a változók számára.

A változódeklaráció helye határozza meg az érvényességi tartományt. A következő ábrán látható négy kategóriát különböztetünk meg:

Érvényességi tartomány

A tagváltozó (member variable) az osztály vagy objektum része. Az osztályon belül, de a metódusokon kívül lehet deklarálni. A tagváltozó az osztály egészében látható.

A lokális változók (local variable) egy kódblokkon belül vannak. A láthatóságuk a deklaráció helyétől az őket közvetlenül körülvevő blokk végéig tart.

A metódusok formális paraméterei (method parameters) az egész metóduson belül láthatók.

A kivételkezelő paraméterek (exception handler parameters) hasonlók a formális paraméterekhez.

Figyeljük meg a következő példát:

if (...) {
    int i = 17;
    ...
}
System.out.println("The value of i = " + i);    //error

Az utolsó sor kívül van az i lokális változó érvényességi körén, ezért a fordítás hibával leáll.

3.4. Változók inicializálása

A lokális és tagváltozókat lehet inicializálni (kezdőértékkel ellátni) a deklarációnál. A változó adattípusa meghatározza a lehetséges kezdőérték típusát is.

byte largestByte = Byte.MAX_VALUE;
short largestShort = Short.MAX_VALUE;
int largestInteger = Integer.MAX_VALUE;
long largestLong = Long.MAX_VALUE;

float largestFloat = Float.MAX_VALUE;
double largestDouble = Double.MAX_VALUE;

char aChar = 'S';
boolean aBoolean = true;

A Java fordító nem engedi meg, hogy inicializálatlan lokális változót használjunk, vagyis az első használat előtt mindenképpen inicializálni kell azt. Tagváltozók esetén a 0 érték alapértelmezett, tehát az inicializálás elmaradása esetén az érték (típustól függő) 0 vagy null lesz. Ennek ellenére jó szokás tagváltozók 0 kezdőértékét is explicit megadni.

A metódusok és konstruktorok formális paramétereinek, valamint a kivételkezelő paramétereknek nem lehet kezdőértéket adni, az értékét a híváskor kapják meg.

Megjegyzés: A C++ nyelvvel szemben tehát a paraméterek esetén nem adható meg konstans kezdőérték. A következő kód csak C++-ban működik, Javában nem:

void move(int x = 1, int y = 1) {...}

Változók inicializálásához a legcélszerűbb ugyanolyan típusú literált megadni, mint a változó. Itt is igaz az az alapelv, hogy az adatvesztéssel járó implicit konverzió nem megengedett, tehát a következő kód hibás:

int i = 3.2;

Megjegyzés: Az előző példában szereplő 3.2 literál double típusú, tehát pl. float változó esetén sem lenne helyes az inicializálás. 3.2f lenne az alkalmas float literált.

3.5. Végleges változók

Változót lehet véglegesen is deklarálni. A végleges változó értékét nem lehet megváltoztatni az inicializálás után. Más nyelvekben ezt konstans változóknak is hívják.

A végleges változók deklarációjánál a final kulcsszót kell használni:

final int aFinalVar = 0;

A végleges lokális változót nem kötelező a deklarációnál inicializálni, de addig nem használhatjuk a változót, amíg nem történik meg az inicializálás:

final int blankFinal;
. . . // nem használható
blankFinal = 0;

3.6. Ellenőrző kérdések

  • Mi az összefüggés a változó neve és értéke között?
  • Mit jelent, hogy egy változót deklarálni kell?
  • Hol kell lennie egy változó deklarációjának?
  • Hogyan kell leírni egy egész típusú változó deklarációját?
  • Mi a legnagyobb és legkisebb érték, amit egy egész típusú változóban tárolhatunk?
  • Mi a különbség a Java értékadó utasítása és a matematikai egyenlőség között?
  • Mi a lebegőpontos típus?

Mit tapasztalunk, ha fordítani és futtatni próbáljuk a következő programot?

public class Test {
    public static void main (String args []) {
        int age;
        age = age + 1;
        System.out.println("The age is " + age);
    }
}
  • Lefordul, majd lefut kimenet nélkül
  • Kiírja a The age is 1 szöveget
  • Lefordul, majd elindul, és futási hibával leáll
  • Nem fordul le

Melyik a helyes forma, ha egy a betűt tartalmazó karakterliterált szeretnénk létrehozni?

  • ’a’
  • ”a”
  • new Character(a)
  • \000a

Milyen értékeket vehet fel egy byte típusú változó?

  • 0 – 65 535
  • (–128) – 127
  • (–32 768) – 32 767
  • (–256) – 255

Melyik nem fordul le?

  • int i = 32;
  • float f = 45.0;
  • double d = 45.0;

Melyik sor fordul le hiba és figyelmeztetés nélkül?

(Minden helyes választ jelöljön meg!)

  • float f=1.3;
  • char c="a";
  • byte b=257;
  • boolean b=null;
  • int i=10;

Melyik korrekt változónév?

(Minden helyes választ jelöljön meg!)

  • 2variable
  • variable2
  • _whatavariable
  • _3_
  • #myvar

Mit tapasztalunk, ha fordítani és futtatni próbáljuk a következő programot?

public class Question01 {
    public static void main(String[] args){
        int y=0;
        int x=z=1;                        // A
        System.out.println(y+","+x+","+z);    // B
    }
}
  • Kiírja: 0, 1, 1
  • Kiírja: 0, 0, 1
  • Fordítási hiba az A jelű sorban
  • Fordítási hiba a B jelű sorban
  • Fordítási hiba mindkét (A és B) sorban