Использование Preferences API

Существует немало случаев, когда программисту необходимо сохранять какие-нибудь конфигурационные параметры. Раньше это можно было сделать используя класс java.util.Properties. Поначалу это выглядело не так уж плохо, но тем не менее на программиста ложилась задача где разместить конфигурационный файл.
PreferencesAPI появился в Java 1.4 и по словам Sun призван обеспечить более удобный способ хранения и восстановления каких-либо настроек (для пользователя или системы). И теперь такого понятия как конфигурационный файл по сути нет. Насколько это хорошо, что нет конфигурационного файла – вопрос открыт. Но система позволяет вам не просто хранить данные, но и делать экспорт/импорт – вы получаете приятный XML, который можно переносить вместе с приложением.
И что еще более важно – теперь система позволяет делать не «плоский» конфигурационный файл, а иерархическую структуру.

Давайте немного рассмотрим как устроено сохрание данных изнутри. Данные настроек пользователя организуются в виде иерархической коллекции узлов – по сути это дерево. Существует два типа деревьев – для пользователя и для системы. Надо также отметить, что для каждого пользователя организуется своя иерархия данных пользователя. Для системы она одна для всех пользователей. Техника работы с обоими типами деревьев одинакова. Потму мы рассмотрим примеры для пользовательского дерева настроек.

Я запускал все примеры под Windows XP – для данной ОС конфигурация хранится в реестре. Вы можете запустить программу regedit и открыть ветку.

HKEY_CURRENT_USER\Software\JavaSoft\Prefs

Если ее там пока нет – не волнуйтесь, появится.

Для Linux создается каталог $HOME/.java/.userPrefs, внутри которого уже создается иерархия из директорий и конечного файла XML.

Давайте сразу рассмотрим несложный пример:

Этот код позволяет нам получить экземпляр объекта Preferences который можно использовать для чтения или записи данных. В данном случае мы будем сохранять и восстанавливать размеры JFrame. Это показано в следующем примере, где мы рассмотрим все более подробно. В нем мы создаем форму с определенными значениями ширины и высоты (100, 200), после этого мы записываем новые значения (400, 500) и при повторном запуске мы получаем их из нашего хранилища.

Давайте внимательно рассмотрим основные моменты в программе.
Во-первых – конструктор. Здесь мы видим. что для начала работы необходимо получить обработчик Preferences для класса. Вызов

создает ветку HKEY_CURRENT_USER\Software\JavaSoft\Prefs\prefexample

Выше мы приводили еще один вариант создания ветки. В этом случае имя будет по умолчанию

HKEY_CURRENT_USER\Software\JavaSoft\Prefs\

Не знаю как создателям, а мне невозможность выбора имени не понравилась. Потому и нашел тот вызов который представлен выше.
Если посмотреть API для класса Preferences, то можно найти немало интересного – что я вам советую сделать после прочтения (если конечно есть время и желание). В принципе вся остальная информация основана именно на этом API.

Во-вторых – в том же конструкторе мы делаем вызов метода setToPreferredSize().
В этом методе мы пытаемся получить параметры по именам. Причем мы указываем не только имя, но и тип – getInt – т.е. просим именно целое число. Preferences включает методы для получения разных типов данных – целые, вещественные, логические, байтовые массивы. Вызов getInt также включает указание значения по умолчанию – если параметр не будет найден.

Таким образом при запуске мы сразу создаем форму и пытаемся в ее конструкторе получить данные из хранилища. Т.к. там еще ничего нет (при первом запуске) то форма получается в размерами 100 на 200. После этого мы делаем вызов putDimensions, который сохраняет новые значения ширины и высоты. Вызовы достаточно просты для понимания – там всего два параметра, имя и значение. Думаю, что после запуска надо посмотреть в реестр и увидеть. что там изменилось.

Еще раз вернемся к вызову

Что здесь очень инетересно, так это то. что вызов node возвращает объект Preferences, который опять же имеет вызов node.
Как легко можно увидеть, это дает нам возможность строить дерево конфигурации – иерархическую структуру. И класс Preferences предоставляет все необходимое для работы с деревом. Это и получение родителя для узла, и получение списка «детей» и другие методы.
Посмотрите результаты вызова

На что я еще хотел бы обратить ваше внимание – Preferences API имеет листенер для отслеживания изменения параметров. Для этого надо реализовать интерфейс PreferenceChangeListener.

Давайте посмотрим несложный пример, который с определенным интервалом меняет высоту и ширину формы, но будет это делать не напрямую, а путем отслеживания изменений сохраненных параметров. Комментарии будут приведены прямо в тексте – я думаю, что это будет удобнее. Порядок просмотра советую выбрать такой – сначала посмотрите на конструктор (в общем-то он не очень сильно изменился). А потом сразу идите в метод resetDimensionsManyTimes. В нем мы в цикле через определенный интервал времени меняем значения параметров и сохраяем их в реестре. При сохранении вызывается обработчик preferenceChange, который считывает новые значение и устанавливает новые размеры формы. Также приведен пример экспорта данных в файл.

Вот и все, что я хотел бы вам рассказать про новое Preferences API. Все пожелания автор принимает с удовольствием.