Как работает java.util.EnumSet <E>?
Класс EnumSet<E>
определяется как:
public abstract class EnumSet<E extends Enum<E>>
extends AbstractSet<E>
implements Cloneable, Serializable
в JCF.
Кроме того, большинство методов, которые реализует сам класс, являются статическими. Наконец, класс не реализует методы add()
, iterator()
, remove()
, size()
, contains()
или isEmpty()
и просто наследует их от AbstractSet, который не реализует их.
У меня есть два вопроса:
- Как точно создаются объекты
EnumSet
?
- Почему я могу использовать метод
add()
для объектов EnumSet
?
Ответы
Ответ 1
Большинство статических методов, которые вы видите, это методы factory (of()
, complementOf()
, allOf()
и т.д.).
Эти методы возвращают экземпляр EnumSet. Фактический тип EnumSet, созданный и возвращаемый этими методами, является подклассом EnumSet (RegularEnumSet
, JumboEnumSet
), которые не являются частью общедоступного API, но реализуют все необходимые методы. Все, что вам нужно знать, это то, что они реализуют EnumSet.
Ответ 2
EnumSet является абстрактным классом, поэтому ему не нужно реализовывать какие-либо абстрактные методы, которые он наследует. Он передает эту ответственность за свои не абстрактные подклассы.
Вы можете вызвать нереализованные методы, потому что вы на самом деле вызываете их в экземпляре подкласса EnumSet. (Поскольку EnumSet является абстрактным, он не может быть непосредственно создан сам.)
Ответ 3
import java.util.*;
enum Foo {
A, B
}
class a {
public static void main(String[] args) {
System.out.println(EnumSet.noneOf(Foo.class));
System.out.println(EnumSet.of(Foo.A));
System.out.println(EnumSet.of(Foo.A).getClass());
}
}
Отпечатки:
[]
[A]
class java.util.RegularEnumSet
Что касается реализации, эта ссылка содержит описание:
EnumSet
является абстрактным классом и обеспечивает два конкретных реализаций, java.util.RegularEnumSet
и java.util.JumboEnumSet
. Основное различие между RegularEnumSet
и JumboEnumSet
заключается в том, что бывший использует переменную long
для хранения элементов, а затем использует long[]
для сохраните его элемент. Поскольку RegularEnumSet
использует переменную long
, которая является 64-битный тип данных, он может удерживать только большую часть элемента. Вот почему когда пустой EnumSet
создается с использованием метода EnumSet.noneOf()
, он выберите RegularEnumSet
, если ключевой юниверс (количество экземпляров enum в Key Enum) меньше или равно 64 и JumboEnumSet
, если ключевой юниверс более 64.
Это означает, что EnumSet
выберет для вас правильную реализацию.
Ответ 4
- Как точно создаются объекты EnumSet?
EnumSet является "абстрактным классом" и предпочтительнее, чем HashSet, когда у вас есть несколько "ключей", которые известны заранее. Например, если у вас есть ключи конфигурации.
производительность лучше, чем HashSet, потому что "... поскольку константы Enum уникальны и имеют заданную длину, так как вы не можете определить новую константу enum в runtime, он позволяет дизайнеру Java API оптимизировать EnumSet..." (Подробнее: http://javarevisited.blogspot.com/2014/03/how-to-use-enumset-in-java-with-example.html#ixzz3jNcyB8ve)
Вы можете создать экземпляр с помощью большого количества методов factory, например EnumSet.of(...)
- Почему я могу использовать метод add() для объектов EnumSet?
После того, как вы создали объект EnumSet, вы можете добавить во время выполнения другой элемент с помощью метода "добавить". Если у вас есть, например, список ключей конфигурации, вы можете представить EnumSet "выбранные" ключи и добавить их во время выполнения.
package sample.test;
import java.util.EnumSet;
public class Foo {
public enum SimpleConfigEnum { KEY1, KEY2, KEY3};
/**
* Example of EnumSet with add
*/
public static void main(String[] args) {
//Create an enumSet with two elements: KEY1,KEY2
EnumSet<SimpleConfigEnum> eSet = EnumSet.of(SimpleConfigEnum.KEY1, SimpleConfigEnum.KEY2);
System.out.println(eSet);
//... add another element --> KEY3
eSet.add(SimpleConfigEnum.KEY3);
System.out.println(eSet);
}
}
Вывод:
[KEY1, KEY2]
[KEY1, KEY2, KEY3]