Хотите добавить элементы в свой набор один раз, а затем только читать его содержимое или хотите добавить элементы в него в любое время? Если вы создадите его один раз, сделайте это так:
class YourClass {
private static void fillSet(Set<SomeType> set) {
// here you add elements, like
set.add(new SomeType());
}
private final static Set<SomeType> yourSetField;
static {
final Set<SomeType> tempSet = new HashSet<SomeType>();
fillSet(tempSet);
yourSetField = Collections.unmodifiableSet(tempSet);
}
}
Теперь - это личное, так что никто за пределами вашего класса не может получить к нему доступ. И его нельзя изменить, поэтому никто не может изменить его содержание.
Если вы хотите добавить элементы в любое время, у вас есть проблема с параллелизмом - прочитайте ответ extraneon.
EDIT
В ответ на запрос я объясню, что делает этот код.
Сначала загадочные <> скобки:
Я предположил, что вы используете Java 1.5 или выше и использовали generics . В двух словах - если вы объявляете переменную типа List, она содержит объекты. Если вы хотите сохранить в нем строки, вы должны их разыграть, когда извлекаете их из своего списка. Пример
List myList = new ArrayList();
myList.add("Hello, my Jon Skeet Number decreases");
String firstElement = (String) myList.get(0);
Требуется приведение к String. Более того, ничто не мешает вам добавить BigDecimal в myList. Но если вы получите его и попытаетесь привести к типу String, вы получите ClassCastException.
myList.add(0, BigDecimal.ZERO); // perfectly legal
String anotherString = (String) myList.get(0); // compiles, but ClassCastException at runtime
Итак, в Java 1.5 введено обобщений . Вы можете указать, что список может содержать только строки. Синтаксис использует <> скобки:
List<String> myList = new ArrayList<String>();
myList.add("Hi everybody");
String firstElem = myList.get(0); // no cast required
myList.add(BigDecimal.ZERO); // compiler error: cannot cast BigDecimal to String
То же относится и к другим коллекциям, таким как наборы. Я писал о списках, потому что поиск из списков удобнее. Я использовал SomeType
в своем примере, потому что я не знал, что вы хотите оставить в своем наборе. Вам следует заменить его типом объектов, которые вы хотите сохранить.
Теперь - статические блоки. Существует два способа инициализации статических полей - непосредственно в их объявлении:
static private int instanceCount = 0;
Это полезно, если начальное значение является простым выражением.
Или в статический блок инициализации
static {
// some code, that can use class static variables, class static methods, declare its own variables etc.
}
Это полезно, если начальное значение для некоторых статических полей требует более сложных вычислений.
А теперь ваши вопросы
- Используется параметр
set
из fillSet
. К этому добавлен элемент: set.add(new SomeType());
- Поскольку я не знал, что вы хотите оставить в своем наборе, я назвал тип его элементов
SomeType
. Он должен быть заменен типом, который вы хотите использовать. new SomeType();
создает экземпляр (гипотетического) SomeType
, вызывающего его конструктор без параметров.
fillSet
делает именно то, что означает его имя - берет набор и заполняет его (добавляет к нему некоторые значения). Мы даем ему пустой набор, чтобы в результате мы получили набор с элементами fillSet
. fillSet
- это место, куда вы должны поместить весь код, который инициализирует ваш набор. Хорошо, что это отделено.
tempSet
- это локальная переменная в блоке статической инициализации, которая назначается один раз и никогда не переназначается. Чтобы выразить это, я объявляю это окончательным. Это привычка, которую я получил от использования findBugs , и я думаю, что это хорошо для удобства чтения.
- Завершение yourSetField означает, что вы не можете написать
yourSetField = new HashSet<SomeType>()
после его инициализации. Но любой, кто может получить доступ к yourSetField
, может написать yourSetField.add(...)
. Если yourSetField
является неизменяемым набором, добавление к нему вызовет исключение во время выполнения (UnsupportedOperationException
). Другими словами: final означает, что вы не можете заставить yourSetField
указывать на другой объект (и компилятор гарантирует это). unmodifiableSet означает, что вы не можете добавлять или удалять объекты из набора. Он будет скомпилирован, но сломается во время выполнения.