JavaRush /Blogue Java /Random-PT /Enum em Java. Exemplos práticos. Adicionando Construtores...

Enum em Java. Exemplos práticos. Adicionando Construtores e Métodos

Publicado no grupo Random-PT
Olá! Hoje falaremos sobre um tipo de dados especial em Java - Enum(abreviação de enumeração). Qual é a sua característica? Vamos imaginar que precisamos implementar meses no programa. Enum.  Exemplos práticos.  Adicionando construtores e métodos - 1Ao que parece, qual é o problema? Você só precisa determinar quais propriedades cada mês possui. Talvez precisemos, em primeiro lugar, do nome do mês e do número de dias que ele contém. A solução para o problema parece bastante simples:
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 +
               '}';
   }
}
Conjunto completo por favor! Temos uma classe Month, os campos necessários, getters-setters, toString(). A menos que equals()você hashCode()precise adicioná-lo para obter felicidade completa :) No entanto, temos um problema conceitual. Como você deve se lembrar, uma das principais vantagens da POO é que ela facilita a modelagem de entidades do mundo real. Uma cadeira, um carro, um planeta - todos esses conceitos da vida cotidiana são fáceis de representar em um programa usando abstração. O problema é que algumas entidades no mundo real têm uma gama estritamente limitada de significados. Existem apenas 4 temporadas em um ano. Existem apenas 7 notas na música. Existem apenas 12 meses no calendário. Ocean tem apenas 11 amigos (embora isso seja discutível :)) Em outras palavras, uma classe Java regular não é capaz de modelar essas entidades e respeitar suas restrições naturais. Nossa classe Monthpossui todos os campos necessários. Mas se outro programador usar, ninguém o impedirá de criar objetos completamente malucos:
public class Main {

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

}
Se isso aparecer no programa, não será fácil encontrar o culpado! Por um lado, o programador que criou os objetos poderia ter entendido que a aula Monthsignificava “mês do ano” e não escrever tal bobagem. Por outro lado, ele estava apenas aproveitando as oportunidades que o designer da turma lhe proporcionou. Posso atribuir quaisquer nomes e número de dias? Ele nomeou. O que fazer em tal situação? Antes do lançamento da versão 1.5 da linguagem Java, os programadores tinham que, francamente, sair dessa :) Naquela época, eles criaram as seguintes construções:
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 +
               '}';
   }
}
Aqui simplificamos o número de meses para três em vez de doze para manter o exemplo mais curto. Tais projetos permitiram resolver o problema. As opções para objetos criados foram limitadas por um construtor privado:
private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
Os programadores que usam a classe não podem simplesmente criar arquivos Month. Eles foram forçados a usar os objetos estáticos finais fornecidos pelo desenvolvedor da classe. Parecia algo assim:
public class Main {

   public static void main(String[] args) {

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

}
No entanto, os desenvolvedores Java notaram um problema existente. Claro, é ótimo que os programadores tenham conseguido encontrar uma solução usando as ferramentas disponíveis na linguagem, mas não parece tão simples! Era necessária uma solução óbvia, acessível até para iniciantes. Foi assim que .apareceu em Java Enum. Essencialmente, Enumé uma classe Java que fornece um conjunto limitado de objetos de valor. Aqui está o que parece:
public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}
Na definição indicamos que Enumse trata de uma classe Java, mas isso é mesmo verdade? Sim, e podemos até verificar. Tente, por exemplo, herdar o nosso enum Monthde alguma outra classe:
public abstract class AbstractMonth {
}

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

   JANUARY,
   FEBRUARY,
   MARCH
}
Por que isso está acontecendo? Quando escrevemos em um programa:
public enum Month
O compilador converte este comando em código como este:
public Class Month extends Enum
Como você já sabe, herança múltipla não é permitida em Java. Portanto, AbstractMonthnão poderíamos herdar de. Como esse novo design pode Enumser usado? E como isso difere do antigo design com static finalcampos? Bem, por exemplo, o design antigo não nos permitia usar nosso próprio conjunto de valores em switch-expressions. Imagine que queremos criar um programa que nos lembre quais feriados são comemorados neste mês:
public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           //error!
           case JANUARY:
       }
   }
}
Aqui, como você pode ver, o compilador gera um erro. Mas depois que o Java 1.5 apareceu enum, tudo ficou muito mais simples:
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);

   }

}
Saída do console:

7 января будет Рождество!
Observação: o acesso aos objetos Enumpermanece estático, como era antes do Java 1.5. Não precisamos criar um objeto Monthpara acessar meses. Ao trabalhar com enumerações, é muito importante não esquecer que Enumesta é uma aula completa. Isso significa que, se necessário, você pode definir construtores e métodos nele. Por exemplo, no trecho de código anterior simplesmente especificamos os valores JANEIRO, FEVEREIRO, MARÇO. No entanto, podemos expandir o nosso enum Monthassim:
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 +
               '}';
   }
}
Aqui adicionamos 2 campos aos nossos enum- o nome do mês e o número de dias, um construtor usando esses campos, getters-setters, um método toString(), bem como 2 métodos estáticos. Como você pode ver, não houve problemas com isso: como dissemos anteriormente, enumesta é uma aula completa:
import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

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

   }

}
Saída do console:

[Month{name='Июнь', daysCount=30}, Month{name='Июль', daysCount=31}, Month{name='Август', daysCount=31}]
Por fim, quero recomendar a você um livro extremamente útil sobre Java, chamado “Effective Java”, de Joshua Bloch . Enum.  Exemplos práticos.  Adicionando construtores e métodos – 3O autor é um dos criadores do Java, então com certeza você pode confiar em seus conselhos sobre o uso correto e competente das ferramentas de linguagem :) Em relação à nossa palestra, aconselho que você preste atenção especial ao capítulo do livro dedicado a enum. Tenha uma leitura produtiva! :)
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION