JavaRush /Java Blog /Random-IT /Enumerazione in Java. Esempi pratici. Aggiunta di costrut...

Enumerazione in Java. Esempi pratici. Aggiunta di costruttori e metodi

Pubblicato nel gruppo Random-IT
Ciao! Oggi parleremo di un tipo di dati speciale in Java - Enum(abbreviazione di enumerazione). Qual è la loro caratteristica? Immaginiamo di dover implementare mesi nel programma. Enum.  Esempi pratici.  Aggiunta di costruttori e metodi - 1Sembrerebbe, qual è il problema? Devi solo determinare quali proprietà ha ogni mese. Forse abbiamo bisogno, prima di tutto, del nome del mese e del numero di giorni in esso contenuti. La soluzione al problema sembra abbastanza semplice:
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 +
               '}';
   }
}
Set completo, per favore! Abbiamo una classe Month, i campi necessari, getter-setter, toString(). A meno che equals()tu hashCode()non abbia bisogno di aggiungerlo per la completa felicità :) Tuttavia, abbiamo un problema concettuale. Come forse ricorderai, uno dei principali vantaggi dell'OOP è che semplifica la modellazione di entità del mondo reale. Una sedia, un'auto, un pianeta: tutti questi concetti della vita quotidiana sono facili da rappresentare in un programma utilizzando l'astrazione. Il problema è che alcune entità nel mondo reale hanno una gamma di significati strettamente limitata. Ci sono solo 4 stagioni in un anno. Nella musica ci sono solo 7 note. Ci sono solo 12 mesi nel calendario. Ocean ha solo 11 amici (anche se questo è discutibile :)) In altre parole, una normale classe Java non è in grado di modellare queste entità e rispettare i loro vincoli naturali. La nostra classe Monthha tutti i campi necessari. Ma se un altro programmatore lo usa, nessuno gli impedirà di creare oggetti del tutto pazzeschi:
public class Main {

   Month month1 = new Month("lolkek", 322);
   Month month2 = new Month("yahoooooooooooo", 12345);

}
Se questo appare nel programma, non sarà facile trovare il colpevole! Da un lato, il programmatore che ha creato gli oggetti avrebbe potuto capire che la classe Monthsignificava “mese dell’anno” e non scrivere simili sciocchezze. D'altra parte, stava solo approfittando delle opportunità che gli aveva fornito il progettista della classe. Posso assegnare qualsiasi nome e numero di giorni? Lo ha nominato lui. Cosa fare in una situazione del genere? Prima del rilascio della versione 1.5 del linguaggio Java, i programmatori dovevano, francamente, uscirne :) A quei tempi, creavano i seguenti costrutti:
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("Январь", 31);
   public static Month FEBRUARY = new Month("Февраль", 28);
   public static Month MARCH = new Month("Март", 31);

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Qui abbiamo semplificato il numero dei mesi a tre anziché a dodici per mantenere l'esempio più breve. Tali progetti hanno permesso di risolvere il problema. Le opzioni per gli oggetti creati erano limitate da un costruttore privato:
private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
I programmatori che utilizzano la classe non potevano semplicemente creare file Month. Sono stati costretti a utilizzare gli oggetti statici finali forniti dallo sviluppatore della classe. Sembrava qualcosa del genere:
public class Main {

   public static void main(String[] args) {

       Month january = Month.JANUARY;
       System.out.println(january);
   }

}
Tuttavia, gli sviluppatori Java hanno notato un problema esistente. Ovviamente è fantastico che i programmatori siano riusciti a trovare una soluzione utilizzando gli strumenti disponibili nel linguaggio, ma non sembra così semplice! Serviva una soluzione ovvia, accessibile anche ai principianti. Ecco come è apparso in Java Enum. Essenzialmente, Enumè una classe Java che fornisce un insieme limitato di oggetti valore. Ecco come appare:
public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}
Nella definizione abbiamo indicato che Enumsi tratta di una classe Java, ma è proprio vero? Sì, e possiamo anche verificarlo. Prova, ad esempio, a ereditare il nostro enum Monthda qualche altra classe:
public abstract class AbstractMonth {
}

//ошибка! No extends clause allowed to enum
public enum Month extends AbstractMonth {

   JANUARY,
   FEBRUARY,
   MARCH
}
Perché sta succedendo? Quando scriviamo ad un programma:
public enum Month
Il compilatore converte questo comando in codice come questo:
public Class Month extends Enum
Come già sai, l'ereditarietà multipla non è consentita in Java. Pertanto, AbstractMonthnon potremmo ereditare da. EnumCome può essere utilizzato questo nuovo design ? E in cosa differisce dal vecchio design con static finali campi? Ebbene, ad esempio, il vecchio design non ci permetteva di utilizzare il nostro insieme di valori nelle switchespressioni -. Immaginiamo di voler creare un programma che ci ricordi quali festività si celebrano questo mese:
public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           //error!
           case JANUARY:
       }
   }
}
Qui, come puoi vedere, il compilatore genera un errore. Ma dopo l'apparizione di Java 1.5 enum, tutto è diventato molto più semplice:
public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           case JANUARY:
               System.out.println("7 января будет Рождество!");
               break;
           case FEBRUARY:
               System.out.println("В феврале празднуется День Защитника Отечества - 23 февраля!");
               break;
           case MARCH:
               System.out.println("В марте отмечается Всемирный Женский День - 8 марта!");
               break;
       }
   }
}



public class Main {

   public static void main(String[] args) {

       HolidayReminder reminder = new HolidayReminder();
       reminder.printHolidays(Month.JANUARY);

   }

}
Uscita console:

7 января будет Рождество!
Nota: l'accesso agli oggetti Enumrimane statico, come avveniva prima di Java 1.5. Non è necessario creare un oggetto Monthper accedere ai mesi. Quando si lavora con le enumerazioni, è molto importante non dimenticare che Enumsi tratta di una classe a tutti gli effetti. Ciò significa che, se necessario, è possibile definire costruttori e metodi al suo interno. Ad esempio, nel pezzo di codice precedente abbiamo semplicemente specificato i valori GENNAIO, FEBBRAIO, MARZO. Tuttavia, possiamo espandere il nostro enum Monthin questo modo:
public enum Month {

   JANUARY("Январь", 31),
   FEBRUARY("Февраль", 28),
   MARCH("Март", 31),
   APRIL("Апрель", 30),
   MAY("Май", 31),
   JUNE("Июнь", 30),
   JULY("Июль", 31),
   AUGUST("Август", 31),
   SEPTEMBER("Сентябрь", 30),
   OCTOBER("Октябрь", 31),
   NOVEMBER("Ноябрь", 30),
   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 +
               '}';
   }
}
Qui abbiamo aggiunto 2 campi ai nostri enum: il nome del mese e il numero di giorni, un costruttore che utilizza questi campi, getter-setter, un metodo toString()e 2 metodi statici. Come puoi vedere, non ci sono stati problemi con questo: come abbiamo detto prima, enumquesta è una classe a tutti gli effetti:
import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

       System.out.println(Arrays.toString(Month.getSummerMonths()));

   }

}
Uscita console:

[Month{name='Июнь', daysCount=30}, Month{name='Июль', daysCount=31}, Month{name='Август', daysCount=31}]
Infine, voglio consigliarvi un libro estremamente utile su Java, ovvero “Effective Java” di Joshua Bloch . Enum.  Esempi pratici.  Aggiunta di costruttori e metodi - 3L'autore è uno dei creatori di Java, quindi puoi sicuramente fidarti dei suoi consigli sull'uso corretto e competente degli strumenti linguistici :) In relazione alla nostra lezione, ti consiglio di prestare particolare attenzione al capitolo del libro dedicato a enum. Buona lettura! :)
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION