Enum
Перечисление — набор именованных констант фиксированного типа.
public enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}public class Main { public static void main(String[] args) { Day today = Day.FRIDAY; System.out.println(today); System.out.println(today.name()); System.out.println(today.ordinal()); for (Day d : Day.values()) { System.out.println(d); } Day parsed = Day.valueOf("SUNDAY"); System.out.println(parsed == Day.SUNDAY); System.out.println(today.compareTo(Day.MONDAY)); }}Константы enum сравнивают через ==. Метод valueOf бросает IllegalArgumentException, если такой константы нет.
Enum в switch
public class Main { static boolean isWeekend(Day day) { return switch (day) { case SATURDAY, SUNDAY -> true; default -> false; }; } public static void main(String[] args) { System.out.println(isWeekend(Day.SUNDAY)); System.out.println(isWeekend(Day.MONDAY)); }}Enum с полями, конструктором и методами
public enum Planet { MERCURY(3.303e+23, 2.4397e6), EARTH(5.976e+24, 6.37814e6), JUPITER(1.9e+27, 7.1492e7); private final double mass; private final double radius; Planet(double mass, double radius) { this.mass = mass; this.radius = radius; } public double surfaceGravity() { return 6.67300E-11 * mass / (radius * radius); }}public class Main { public static void main(String[] args) { for (Planet p : Planet.values()) { System.out.printf("%s: %.2f%n", p, p.surfaceGravity()); } }}Конструктор enum всегда приватный.
Enum с поведением
Каждая константа может переопределять метод:
public enum Operation { ADD("+") { @Override public int apply(int a, int b) { return a + b; } }, SUBTRACT("-") { @Override public int apply(int a, int b) { return a - b; } }, MULTIPLY("*") { @Override public int apply(int a, int b) { return a * b; } }; private final String symbol; Operation(String symbol) { this.symbol = symbol; } public String getSymbol() { return symbol; } public abstract int apply(int a, int b);}public class Main { public static void main(String[] args) { for (Operation op : Operation.values()) { System.out.println("6 " + op.getSymbol() + " 3 = " + op.apply(6, 3)); } }}Так вместо цепочки if/switch поведение хранится прямо в константе.
Enum и интерфейсы
public interface Priced { double price();}public enum Coffee implements Priced { ESPRESSO(2.5), LATTE(3.5), CAPPUCCINO(3.2); private final double price; Coffee(double price) { this.price = price; } @Override public double price() { return price; }}EnumMap и EnumSet
Специализированные коллекции для enum, быстрые и компактные:
import java.util.EnumMap;import java.util.EnumSet;import java.util.Map;import java.util.Set;public class Main { public static void main(String[] args) { Map<Day, String> plan = new EnumMap<>(Day.class); plan.put(Day.MONDAY, "Работа"); plan.put(Day.SATURDAY, "Отдых"); System.out.println(plan); Set<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY); Set<Day> workdays = EnumSet.complementOf(weekend); System.out.println(workdays); }}Record
Запись — компактный способ объявить неизменяемый класс-носитель данных (Java 16+).
public record Point(int x, int y) {}Компилятор сам создает:
- приватные
finalполя; - конструктор со всеми полями;
- методы доступа
x()иy(); equals,hashCode,toString.
public class Main { public static void main(String[] args) { Point p = new Point(3, 4); System.out.println(p); System.out.println(p.x() + " " + p.y()); System.out.println(p.equals(new Point(3, 4))); }}Вывод:
Point[x=3, y=4]3 4trueКомпактный конструктор
Для проверки и нормализации значений:
public record Range(int from, int to) { public Range { if (from > to) { throw new IllegalArgumentException("from > to: " + from + " > " + to); } } public int length() { return to - from; } public static Range of(int from, int to) { return new Range(from, to); }}public record Email(String value) { public Email { value = value.trim().toLowerCase(); if (!value.contains("@")) { throw new IllegalArgumentException("Некорректный email: " + value); } }}Ограничения record
- нельзя наследовать от другого класса, но можно реализовывать интерфейсы;
- нельзя объявлять поля экземпляра сверх компонентов;
- запись неявно
final; - можно добавлять методы и статические члены.
public interface HasArea { double area();}public record Rectangle(double width, double height) implements HasArea { @Override public double area() { return width * height; }}Record и pattern matching
Деконструкция записей в switch и instanceof (Java 21):
public sealed interface Shape permits Circle, Square {}public record Circle(double radius) implements Shape {}public record Square(double side) implements Shape {}public class Main { static double area(Shape shape) { return switch (shape) { case Circle(double r) -> Math.PI * r * r; case Square(double s) -> s * s; }; } public static void main(String[] args) { System.out.printf("%.2f%n", area(new Circle(1))); System.out.println(area(new Square(3))); }}Когда что использовать
- enum — фиксированный набор значений, известный заранее: дни недели, статусы, типы операций.
- record — простой неизменяемый объект данных: координаты, DTO, результат запроса.
- class — когда нужны изменяемое состояние, наследование или сложное поведение.
