Utolsó módosítás: 2016.10.26.
final
módosítóAmenyiben nem szeretnénk, hogy egy változó értéke inicializálása után megváltozzon, elláthatjuk final
módosítóval. Egy ilyen változó értékének felülírása fordítási hibát eredményez:
FinalErr.java:4: error: cannot assign a value to final variable n
n = 2;
^
vagy
FinalErr.java:6: error: variable n might already have been assigned
n = 1;
^
Egy módosíthatatlan változó esetén ügyelni kell, hogy csak egyszer, az inicializálás során adjunk értéket. Az n
változó deklarációja és inicializációja (röviden definíciója) az alábbi:
final int n = 0;
Amennyiben egy osztály adattagja módosíthatatlan, akkor szintén oda kell figyelni az inicializációra. A változót inicializálhatjuk is rögtön a deklaráció helyén, vagy a konstruktorokban adunk neki értéket egyszer.
class A {
final int n = 0; // ok
}
class B {
final boolean b;
public B() {
b = true; // ok, első értékadás
b = false; // hibás
}
A final
módosítónak az osztályok közötti öröklődéssel kapcsolatban is van jelentése. Erről az öröklődésnél lesz szó.
Az interfészek lehetővé teszik a szoftver tervezését anélkül, hogy a megvalósításra kelljen gondolnunk.
Egy interfész definíciója változók és metódusok deklarációjának és, a Java 8-as verziójával kezdve, metódusok definíciójának sorozata.
Az interfészen belüli változók alapértelmezés szerint public final static
módosítókkal vannak ellátva, ezért ezeket kitenni felesleges. A metódus deklarációk és definíciók alapértelmezetten public
láthatósággal rendelkeznek, így ezt sem kell kitenni.
public interface Car {
boolean b = true; // ok
int a = b; // hibás
int b = 2; // ok
int c = c * 3; // hibás
void accelerate(); // ok
}
Egy interfész egy új referencia típust vezet be. Létrehozhatunk egy változót, melynek típusa valamely interfész (például a fenti Car
). Ekkor a változónak értékül adhatjuk bármely olyan objektum referenciáját, melynek osztálya megvalósítja az interfészt. Például, ha a fenti Car
interfészt megvalósítja a Google önvezető járműve, akkor az alábbi kód helyes:
Car c = new GoogleCar();
Az interfészek kapcsolatban állhatnak egymással: ezt a kapcsolatot kiterjesztésnek nevezzük, melyet az extends
kulcsszóval jelzünk. Eszerint az interfészek szülő-gyermek viszonyban állnak egymással. Egy interfész tehát a törzsében deklarált változókból és metódusokból, illetve az általa kiterjesztett interfészek váltózóiból és metódusaiból áll.
public interface SelfDrivingCar extends Car, GPS {
void driveToLocation(Position coordinates);
}
Egy osztály abban az esetben implementál egy interfészt, ha annak minden metódusához rendel törzset. Ehhez jelezni kell a szándékot az osztály definíciójának fejlécében az implements
kulcsszót használva, és minden, az interfészben deklarált metódusnak nyilvánosnak kell lennie. Ellenkező esetben a fordító hibát jelez.
public class GoogleCar implements SelfDrivingCar {
public void accelerate() { /* ... */ }
public void driveToLocation(Position coordinates) { /* ... */ }
/* A GPS interfész műveletei */
}
Egy közismert interfész a java.lang.Comparable
. Ezt megvalósítják azok az osztályok, melyek objektumai összehasonlíhatók: java.lang.Integer
, java.lang.String
, java.util.Date
stb.
A java.lang.Comparable
interfész egyetlen művelete a compareTo()
, mely paraméterül vár egy másik objektumot. A compareTo()
negatív egészt ad vissza, ha a this
objektum kisebb, mint a paraméter, nullát, ha egyenlők, és pozitív egészt, ha a this
nagyobb, mint a paraméter valamilyen reláció szerint.
public interface Comparable<T> {
int compareTo(T other);
}
Például:
Integer n = 2;
Integer m = 4;
n.compareTo(m); // -1
Készítsük el a publikus geometry.Movable
interfészt! Ez deklarálja a move()
metódust, mely paraméterül vár két int
típusú távolságot (függőleges és vízszintes), és nincs visszatérési értéke.
Készítsük el a publikus geometry.Figure
interfészt! Ez kiterjeszti a fenti Movable
és a java.lang.Comparable<Figure>
interfészt az alábbi metódusokkal:
Egy double
visszatérési típusú area()
, mely kiszámolja a síkidom területét.
Egy String
visszatérési típusú show()
, mely visszaadja a síkidom szöveges reprezentációját.
Valamint a Comparable
interfész compareTo()
metódusának adjunk egy alapértelmezett definíciót! Ez a síkidomokat területük alapján hasonlítja össze. Az a nagyobb síkidom, amelyiknek a területe nagyobb.
Készítsük el a publikus geometry.Circle
osztályt, mely egy kört fog ábrázolni! Az osztály megvalósítja a Figure
interfész műveleteit.
Deklaráljunk három privát int
adattagot, melyek a kör közepének koordinátáit és a kör sugarát tárolják!
Készítsünk egy konstruktort, mely paraméterül várja a kör középpontjának x, y koordinátáit és a kör sugarát, és ezekkel inicializálja az adattagokat!
Készítsünk egy alapértelmezett konstruktort is, mely a kör középpontját az origóba és a kör sugarát 1-re állítja!
Valósítsuk meg a Figure
interfész műveleteit! Ezek a következők: move()
, area()
, compareTo()
és show()
.
A show()
eredményére egy lehetséges példa: "Circle at (2,4) radius: 5"
Készítsük el a publikus geometry.Square
osztályt, melynek egy objektuma egy négyzetet fog ábrázolni! Ez az osztály is megvalósítja a Figure
interfész műveleteit.
Deklaráljunk három privát, int
típusú adattagot, melyek a négyzet bal felső sarkának koordinátáit és a négyzet oldalának hosszát ábrázolják!
Definiáljunk egy konstruktort, mely paraméterül várja az adattagok kezdeti értékét, és ezekkel inicializálja az objektumot!
Definiáljunk egy alapértelmezett konstruktort, mely a bal felső sarkot az origóba, az oldal hosszát 1-re állítja.
Valósítsuk meg a Figure
interfész műveleteit! Ezek a következők: move()
, area()
és show()
.
A show()
eredményére egy lehetséges példa: "Square at (1,-2) side: 3"
Készítsük el a geometry
csomagon kívül a FigureDemo
osztályt! Definiáljuk az alábbi két metódust:
Egy statikus, Figure
visszatérési típusú biggest
metódust, mely paraméterül várja Figure
referenciák listáját (elfogadunk ArrayList
-et és LinkedList
-et is, ezért várjunk paraméterül egy List
referenciát)!
A metódus egy maximumkiválasztást valósít meg a síkidomokon, és visszaadja a listából a legnagyobb területű síkidom referenciáját. Két síkidom összehasonlításához használjuk a compareTo()
metódust! Használjunk iterátort a paraméter lista bejárására! Iterátort a lista iterator()
metódusával tudunk kérni.
Írjunk main()
metódust a biggest()
kipróbálására! Inicializáljunk egy List
referenciát egy LinkedList
objektummal és töltsük föl néhány síkidommal. Írassuk is ki a legnagyobb síkidom szöveges reprezentációját!