Szia! Ma a Java egyik speciális adattípusáról fogunk beszélni:
Nem tűnik problémásnak, igaz? Csak azt kell meghatároznunk, hogy melyik hónap milyen tulajdonságokkal rendelkezik. Talán először a hónap nevére és a benne lévő napok számára van szükségünk. A megoldás meglehetősen egyszerűnek tűnik:
A szerző a Java egyik megalkotója, így a nyelvi eszközök helyes és hozzáértő használatára vonatkozó tanácsaiban mindenképp megbízhat :) Tanóránkkal kapcsolatban azt javaslom, hogy fordítsanak különös figyelmet a könyv című fejezetére
Enum
(a "felsorolás" rövidítése). Mitől különleges? Képzeljük el, mi kell ahhoz, hogy "hónapokat" megvalósítsunk egy programban. 
public class Month {
private String name;
private int daysCount;
public Month(String name, int daysCount) {
this.name = name;
this.daysCount = daysCount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getDaysCount() {
return daysCount;
}
public void setDaysCount(int daysCount) {
this.daysCount = daysCount;
}
@Override
public String toString() {
return "Month{" +
"name='" + name + '\'' +
", daysCount=" + daysCount +
'}';
}
}
Az egész shabang! Van egy Month
osztályunk, a kötelező mezők, a getter/setterek és a toString()
. Kivéve persze, ha hozzá kell adnunk equals()
éshashCode()
a teljes boldogság eléréséhez :) De itt van egy fogalmi problémánk. Valószínűleg emlékszel rá, hogy az OOP egyik fő előnye, hogy megkönnyíti az entitások valós világból való modellezését. Szék, autó, bolygó – mindezek a hétköznapi élet fogalmai könnyen ábrázolhatók egy programban az absztrakció segítségével. A probléma az, hogy néhány valós entitásnak szigorúan korlátozott értéktartománya van. Csak 4 évszak van egy évben. Csak 8 hang van egy oktávban. A naptár mindössze 12 hónapos. Danny Ocean of Ocean's 11-nek pedig csak 11 barátja van (bár ez nem számít :)) Ami számít, az az, hogy egy közönséges Java osztály nem képes modellezni ezeket az entitásokat és érvényesíteni természetes korlátaikat. A miénkMonth
osztályban minden kötelező mező szerepel. De ha egy másik programozó használja, senki sem akadályozhatja meg abban, hogy teljesen őrült objektumokat hozzon létre:
public class Main {
Month month1 = new Month("lolkek", 322);
Month month2 = new Month("yahoooooooooooo", 12345);
}
Ha ez megjelenik a kódunkban, nem lesz könnyű megtalálni a tettest! Egyrészt az objektumokat létrehozó programozó rájönhet, hogy az Month
osztály azt jelenti, hogy "hónap egy évben", és nem ír ilyen hülyeségeket. Másrészt a programozó csak az osztálytervező által biztosított képességeket használja ki. Lehet-e tetszőleges neveket és napszámokat rendelni? Pontosan ezt kaptuk. Mit tegyünk akkor ebben a helyzetben? Őszintén szólva, a Java 1.5 megjelenése előtt a programozóknak kreatívkodniuk kellett :) Abban az időben ilyen struktúrákat készítettek:
public class Month {
private String name;
private int daysCount;
private Month(String name, int daysCount) {
this.name = name;
this.daysCount = daysCount;
}
public static Month JANUARY = new Month("January", 31);
public static Month FEBRUARY = new Month("February", 28);
public static Month MARCH = new Month("March", 31);
@Override
public String toString() {
return "Month{" +
"name='" + name + '\'' +
", daysCount=" + daysCount +
'}';
}
}
Itt tizenkettőről háromra csökkentettük a hónapok számát, hogy rövidebb legyen a példa. Az ilyen tervek lehetővé tették a probléma megoldását. Az objektumok létrehozásának lehetősége egy privát konstruktorra korlátozódott:
private Month(String name, int daysCount) {
this.name = name;
this.daysCount = daysCount;
}
Az osztályt használó programozók nem tudtak egyszerűen Month
objektumokat létrehozni. Az osztályfejlesztő által biztosított végső statikus objektumokat kellett használniuk. Például így:
public class Main {
public static void main(String[] args) {
Month january = Month.JANUARY;
System.out.println(january);
}
}
A Java fejlesztői azonban felhívták a figyelmet a fennálló problémára. Persze nagyon jó, hogy a programozók a nyelven elérhető eszközök segítségével ki tudtak találni egy megoldást, de ez nem tűnik túl egyszerűnek! Kézenfekvő megoldásra volt szükség, még a kezdők számára is. És így Enum
jelent meg a Java-ban. Alapvetően Enum
egy Java osztály, amely korlátozott objektumértékeket biztosít. Így néz ki:
public enum Month {
JANUARY,
FEBRUARY,
MARCH
}
A definícióban jeleztük, hogy ez Enum
egy Java osztály, de ez tényleg igaz? Igen, és még ellenőrizni is tudjuk. Például próbálja meg az enumunkat örökölni Month
egy másik osztályt:
public abstract class AbstractMonth {
}
// Error! The extends clause cannot be used with an enum
public enum Month extends AbstractMonth {
JANUARY,
FEBRUARY,
MARCH
}
Miért történik ez? Amikor írunk:
public enum Month
a fordító ezt az utasítást a következő kódra alakítja:
public Class Month extends Enum
Mint már tudja, a Java nem támogatja a többszörös öröklődést. Ezért nem örökölhetünk AbstractMonth
. Hogyan Enum
használható ez az új konstrukció, ? És miben különbözik a régi, szántóföldi konstrukciótól static final
? Nos, például a régi konstrukció nem engedte, hogy a saját értékkészletünket használjuk a kijelentésekben switch
. Képzeljük el, hogy olyan programot szeretnénk létrehozni, amely emlékeztet minket a minden hónapban megünnepelt ünnepekre:
public class HolidayReminder {
public void printHolidays(Month month) {
switch (month) {
// Error!
case JANUARY:
}
}
}
Mint látható, a fordító itt hibát dob. De miután enum
megjelent a Java 1.5-ben, minden sokkal egyszerűbb lett:
public enum Month {
JANUARY,
FEBRUARY,
MARCH
}
public class HolidayReminder {
public void printHolidays(Month month) {
switch (month) {
case JANUARY:
System.out.println("New Year's Day is January 1st!");
break;
case FEBRUARY:
System.out.println("Valentine's Day is February 14th!");
break;
case MARCH:
System.out.println("Saint Patrick's Day is March 17th!");
break;
}
}
}
public class Main {
public static void main(String[] args) {
HolidayReminder reminder = new HolidayReminder();
reminder.printHolidays(Month.JANUARY);
}
}
Konzol kimenet:
New Year's Day is January 1st!
Vegye figyelembe, hogy az Enum
objektumokhoz való hozzáférés statikus maradt, akárcsak a Java 1.5 előtt. Nem kell objektumot létrehoznunk Month
a hónapok eléréséhez. Az enumokkal való munka során nagyon fontos, hogy ne felejtsük el, hogy ez Enum
egy teljes értékű osztály. Ez azt jelenti, hogy szükség esetén konstruktorokat és metódusokat definiálhatunk benne. Például az előző kódrészletben egyszerűen megadtuk az értékeket: JANUÁR, FEBRUÁR, MÁRCIUS. Month
A felsorolásunkat azonban a következőképpen bővíthetjük :
public enum Month {
JANUARY("January", 31),
FEBRUARY("February", 28),
MARCH("March", 31),
APRIL("April", 30),
MAY("May", 31),
JUNE("June", 30),
JULY("July", 31),
AUGUST("August", 31),
SEPTEMBER("September", 30),
OCTOBER("October", 31),
NOVEMBER("November", 30),
DECEMBER("December", 31);
private String name;
private int daysCount;
Month(String name, int daysCount) {
this.name = name;
this.daysCount = daysCount;
}
public static Month[] getWinterMonths() {
return new Month[]{DECEMBER, JANUARY, FEBRUARY};
}
public static Month[] getSummerMonths() {
return new Month[]{JUNE, JULY, AUGUST};
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getDaysCount() {
return daysCount;
}
public void setDaysCount(int daysCount) {
this.daysCount = daysCount;
}
@Override
public String toString() {
return "Month{" +
"name='" + name + '\'' +
", daysCount=" + daysCount +
'}';
}
}
Itt megadtuk a enum
2 mezőnket (a hónap neve és a napok száma), egy konstruktort, amely ezeket a mezőket használja, a getter/settereket, a toString()
metódust és 2 statikus metódust. Mint látható, ezzel nem volt probléma. Ismét Enum
egy teljes értékű osztály:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
System.out.println(Arrays.toString(Month.getSummerMonths()));
}
}
Konzol kimenet:
[Month{name='June', daysCount=30}, Month{name='July', daysCount=31}, Month{name='August', daysCount=31}]
Végül szeretnék ajánlani egy rendkívül hasznos Java könyvet, mégpedig Joshua Bloch "Effective Java" című könyvét . 
Enum
. Jó olvasást! :)
GO TO FULL VERSION