Java. Лучшая практика работы с Enum
Решил объединить и написать все в одной статье про Enum, статья не совсем для новичков.
Enum - это отдельный тип в Java, иногда его называют перечисление. Проще говоря, это константы, которые связаны между собой - времена года, дни недели, планеты солнечной системы, роли в системе и т.д.
Содержание:
- Пример простенького Enum
- Emun и switch:
- Методы Enum
- Сравнение Enum
- Проблема toString()
- Конструкторы в Enum
- Методы в Enum
- Enum и stream()
- EnumSet
Пример простенького Enum:
public enum UserTypeEnum {
ADMIN,
MAIN_MODERATOR,
MODERATOR,
SPECTATOR,
BUYER,
SELLER;
}
Вывести все значения Enum
через простой цикл:
for (UserTypeEnum role : UserTypeEnum.values()) {
System.out.println(role);
}
Вывести все значения Enum
через StreamAPI:
Arrays.stream(UserTypeEnum.values())
.forEach(role->{
System.out.println(role);
});
Emun может быть в switch:
public void switchEnum(UserTypeEnum type) {
switch (type) {
case ADMIN:
System.out.println("Выбрали админа");
break;
case MAIN_MODERATOR:
System.out.println("Выбрали главного модератора");
break;
case MODERATOR:
System.out.println("Выбрали модератора");
break;
case SPECTATOR:
System.out.println("Выбрали наблюдателя");
break;
default:
System.out.println("Роль не из упраления " + type);
break;
}
}Важные методы:
1.name() - возвращает имя константыв String
UserTypeEnum c1 = UserTypeEnum.ADMIN;
// так с1 это тип UserTypeEnum
String c1 = UserTypeEnum.ADMIN.name();
// так с1 это тип String
2.ordinal() - возвращает порядковый номер, начиная с 0
int num0 = UserTypeEnum.ADMIN.ordinal(); // вывод 0,//т.к. ADMIN первый в спискеint num1 = UserTypeEnum.MAIN_MODERATOR.ordinal();// вывод 1,//т.к. MAIN_MODERATOR второй в списке3.values() - получаем массиввсех значений в EnumПримеры - выше, как перебрать все значения Enum4.valueOf() - получить Enum по строкеUserTypeEnum admin = UserTypeEnum.valueOf("ADMIN");
System.out.println(admin.ordinal()); // будет выведено 0Если значения нет, то получите java.lang.IllegalArgumentExceptionUserTypeEnum admin = UserTypeEnum.valueOf("ADMIn");
System.out.println(admin.ordinal());Exception in thread "main" java.lang.IllegalArgumentException:
No enum constant testEnum.UserTypeEnum.ADMIn
Сравнение Enum:
Enum можно сравнивать и через == и через метод equals
boolean b1 = UserTypeEnum.ADMIN.equals(UserTypeEnum.ADMIN);
System.out.println(b1); //true
boolean b2 = UserTypeEnum.ADMIN == UserTypeEnum.ADMIN;
System.out.println(b2); //trueПочему лучше использовать ==, а не equalsUserTypeEnum user = null;
boolean b = user.equals(UserTypeEnum.ADMIN);Тут мы получим NullPointerExceptionПоэтому лучше сравнивать через ==Опасность toString():
По дефолту toString возвращает тоже самое, что и name(),те имя константы в StringString adm = UserTypeEnum.ADMIN.toString();
System.out.println(adm); //ADMINНо, метод toString может быть переопределен в нашем Enum@Override
public String toString() {
return "UserTypeEnum{" +
"roleId=" + roleId +
", groupRoles=" + groupRoles +
", isEditUserComments=" + isEditUserComments +
", isEditModeratorComments=" + isEditModeratorComments +
", access='" + access + '\'' +
'}';
}И тогда:String adm = UserTypeEnum.ADMIN.toString();
System.out.println(adm); //UserTypeEnum{roleId=1, groupRoles=ADMIN,
// isEditUserComments=true, isEditModeratorComments=true,// access='полный доступ'}Поэтому использовать toString необходимо ТОЛЬКО для для вывода данныхв консоль, файл и тп, но если вам надо получить имя константытипа String то используйте name()Конструкторы в Enum:
Enum могут выглядеть и сложноpublic enum UserTypeEnum {
// admins group
ADMIN(1, "admin", true, true, "полный доступ"),
MAIN_MODERATOR(2, "moderator", true, true, "полный доступ"),
MODERATOR(3, "moderator", true, true, "частичный доступ"),
SPECTATOR(4, "spectator", false, false, "только наблюдение"),
// users group
BUYER(5, "client", true, false, "раздел покупателей"),
SELLER(6, "client", false, false, "раздле продавцов");
private int roleId;
private String types;
private boolean isEditUserComments;
private boolean isEditModeratorComments;
private String access;
UserTypeEnum(int roleId, String types, boolean isEditUserComments, boolean isEditModeratorComments, String access) {
this.roleId = roleId;
this.types = types;
this.isEditUserComments = isEditUserComments;
this.isEditModeratorComments = isEditModeratorComments;
this.access = access;
}
public int getRoleId() {
return roleId;
}
public String getTypes() {
return types;
}
public boolean isEditUserComments() {
return isEditUserComments;
}
public boolean isEditModeratorComments() {
return isEditModeratorComments;
}
public String getAccess() {
return access;
}
}Проверить, может ли SPECTATOR редактировать пользовательскиекомментарии:boolean b = UserTypeEnum.SPECTATOR.isEditUserComments(); //falseEnum могут быть и приватными (когда находятся внутри другого Класса
или Enum):
public enum UserTypeEnum {
// admins group
ADMIN(1, GroupRoles.ADMIN, true, true, "полный доступ"),
MAIN_MODERATOR(2, GroupRoles.MODERATOR, true, true, "полный доступ"),
MODERATOR(3, GroupRoles.MODERATOR, true, true, "частичный доступ"),
SPECTATOR(4, GroupRoles.SPECTATOR, false, false, "только наблюдение"),
// users group
BUYER(5, GroupRoles.CLIENT, true, false, "раздел покупателей"),
SELLER(6, GroupRoles.CLIENT, false, false, "раздле продавцов");
private int roleId;
private GroupRoles groupRoles;
private boolean isEditUserComments;
private boolean isEditModeratorComments;
private String access;
private enum GroupRoles{
ADMIN, MODERATOR, SPECTATOR,CLIENT
}
UserTypeEnum(int roleId, GroupRoles groupRoles, boolean isEditUserComments, boolean isEditModeratorComments, String access) {
this.roleId = roleId;
this.groupRoles = groupRoles;
this.isEditUserComments = isEditUserComments;
this.isEditModeratorComments = isEditModeratorComments;
this.access = access;
}
public int getRoleId() {
return roleId;
}
public GroupRoles getGroupRoles() {
return groupRoles;
}
public boolean isEditUserComments() {
return isEditUserComments;
}
public boolean isEditModeratorComments() {
return isEditModeratorComments;
}
public String getAccess() {
return access;
}
}Здесь у нас есть приватный Enum GroupRoles, те такой Enum в Enum.Enum может содержать методы:
public static UserTypeEnum getUserTypeEnumByRoleId(int roleId) {
return Arrays.stream(UserTypeEnum.values()).filter(e -> e.getRoleId() == roleId).findFirst().
orElseThrow(() -> new IllegalStateException("Cant find roleId " + roleId));
}Получаем Enum по id ролиpublic static Set<UserTypeEnum> userTypeFilter(Predicate<UserTypeEnum> p) {
return Arrays.stream(UserTypeEnum.values()).filter(p).collect(Collectors.toSet());
}Или же можно просто передавать предикат, и фильтровать Enumкак на захочется:UserTypeEnum user = UserTypeEnum.getUserTypeEnumByRoleId(4);
System.out.println(user); //SPECTATOR
Set<UserTypeEnum> users = UserTypeEnum.userTypeFilter(u -> u.isEditUserComments());
System.out.println(users); //[MODERATOR, BUYER, MAIN_MODERATOR, ADMIN]Упростить методы, благодаря методу,
который возвращает stream
Методы getUserTypeEnumByRoleId и userTypeFilter можно существенноупростить, добавив метод stream:private static Stream<UserTypeEnum> stream() {
return Arrays.stream(UserTypeEnum.values());
}И наши методы теперь выглядят вот так (нам не надо писать длиннуюконструкцию Arrays.stream(UserTypeEnum.values())):public static UserTypeEnum getUserTypeEnumByRoleId(int roleId) {
return stream().filter(e -> e.getRoleId() == roleId).findFirst().
orElseThrow(() -> new IllegalStateException("Cant find roleId " + roleId));
}
public static Set<UserTypeEnum> userTypeFilter(Predicate<UserTypeEnum> p) {
return stream().filter(p).collect(Collectors.toSet());
}
Работа с EnumSet
EnumSet - это коллекция Set для работы с Enum.Используйте EnumSet вместо HashSet Методы:1.allOf - Enum содержит весь Enum:EnumSet<UserTypeEnum> allUserType = EnumSet.allOf(UserTypeEnum.class);System.out.println(allUserType);
Вывод на консоль:[ADMIN, MAIN_MODERATOR, MODERATOR, SPECTATOR, BUYER, SELLER]
2.range - создать подмножество Enum:EnumSet<UserTypeEnum> rangeUserType = EnumSet.range(UserTypeEnum.ADMIN, UserTypeEnum.SPECTATOR);
System.out.println(rangeUserType);Вывод на консоль:[ADMIN, MAIN_MODERATOR, MODERATOR, SPECTATOR]
3.complementOf- создать подмножество Enum, исключая другоеEnumSet<UserTypeEnum> userGroup = EnumSet.complementOf(rangeUserType);
System.out.println(userGroup);Вывод на консоль:[BUYER, SELLER]
4.of- создать подмножество Enum, указывая конкретные Enum:EnumSet<UserTypeEnum> group = EnumSet.of(UserTypeEnum.SPECTATOR, UserTypeEnum.BUYER,UserTypeEnum.SELLER);
System.out.println(group);Вывод на консоль:[SPECTATOR, BUYER, SELLER]
5.noneOf - создать пустой EnumSet и туда добавить данные
можно через add:
EnumSet<UserTypeEnum> group = EnumSet.noneOf(UserTypeEnum.class);
group.add(UserTypeEnum.BUYER);
group.add(UserTypeEnum.SELLER);
System.out.println(group);Вывод на консоль:[BUYER, SELLER]
6. copyOf - для копирования всех элементов из любой коллекции
List<UserTypeEnum> listUserType = new ArrayList<>();
listUserType.add(UserTypeEnum.ADMIN);
EnumSet<UserTypeEnum> listUserCopy = EnumSet.copyOf(listUserType);
System.out.println(listUserCopy);Вывод на консоль:[ADMIN]
Комментарии
Отправить комментарий