Java: Ленивая загрузка слов из словаря: как сделать статический финал? - PullRequest
0 голосов
/ 30 мая 2011

У меня есть программа, которая использует список слов (скажем, все слова в / usr / share / dict / words). Список слов никогда не изменяется, поэтому я думаю, что я должен сделать его статическим окончательным. Но как мне сделать это окончательно? Моя текущая реализация выглядит следующим образом (я лениво загружаю список слов, когда это необходимо, хотя я не уверен, что ленивая часть необходима, так как список не такой большой или медленный для загрузки):

private static List<String> WORDS; // adding a final modifier doesn't work here

private static List<String> getWords() throws IOException {
  if (WORDS == null) {
    List<String> words = new LinkedList<String>();
    String line;
    BufferedReader br = new BufferedReader(new FileReader("my_dictionary.txt"));
    while ((line = br.readLine()) != null) {
      words.add(line);
    }
    WORDS = words;
  }
  return WORDS;
}

В приведенном выше коде мне не разрешено делать WORDS final. Любые предложения о том, как это сделать? (Действительно ли имеет значение, делаю ли я это final или нет?)

РЕДАКТИРОВАТЬ: я думаю, один из способов сделать это с помощью следующего:

private static final List<String> WORDS = getWords();

private static List<String> getWords() throws IOException {
  List<String> words = new LinkedList<String>();
  String line;
  try {
    BufferedReader br = new BufferedReader(new FileReader("my_dictionary.txt"));
    while ((line = br.readLine()) != null) {
      words.add(line);
    }
  } catch (IOException e) {
    System.out.println("Error reading dictionary: " + e);
  }
  return words;
}

Но это теряет ленивую часть загрузки (хотя, может быть, это не так важно, как быть final? Может быть, я слишком стараюсь сделать что-то "книгой"?).

Ответы [ 4 ]

3 голосов
/ 30 мая 2011

Вы можете использовать ImmutableList из библиотек Guava , чтобы предотвратить его изменение.

Так что вы можете сделать что-то вроде этого:

private static List<String> WORDS;

private static List<String> getWords() throws IOException {
  if (WORDS == null) {
    List<String> words = new LinkedList<String>();
    String line;
    BufferedReader br = new BufferedReader(new FileReader("my_dictionary.txt"));
    while ((line = br.readLine()) != null) {
      words.add(line);
    }
    WORDS = ImmutableList.copyOf(words);
  }
  return WORDS;
}
1 голос
/ 30 мая 2011

Есть несколько вещей, о которых нужно помнить:

  • Когда вы объявляете List окончательным, конечной является только ссылка на объект.Содержимое списка может быть изменено.Так что, если вы пытаетесь не допустить изменения содержимого списка, финал вам не поможет.Вам понадобится какая-то коллекция Immutable, как упоминает Jits.
  • Вы можете присвоить значение конечной переменной во время инициализации класса или в конструкторе.Таким образом, вы можете пойти дальше и назначить пустой список при инициализации класса, а затем выполнять отложенную загрузку в любое время.
1 голос
/ 30 мая 2011

Единственный способ сделать это - установить переменную в качестве статического финала и затем инициализировать ее в статическом разделе, как показано ниже:

static final Collection<String> WORDS;

static {
    try {
        WORDS = new ArrayList<String>();
        // Load dict into variable
    } catch (...) {...}
}

Проблема в том, что невозможно определить, что произошло, если было сгенерировано исключение. Это просто прекратит выполнение статического блока. Если вещи были частично инициализированы, вы не будете знать.

Вероятно, лучше настроить переменную в синглтоне и всегда получать ее таким образом. Это обеспечит его инициализацию только один раз.

0 голосов
/ 13 февраля 2013

В дополнение к тому, что MBCook сказал, вы можете добавить команду throw в предложении catch, чтобы выбросить исключение как RuntimeException (не проверено), если вы уверены, что условие сбоя блокирует (хотя вы должны быть действительно уверены).Например, в моем случае у меня есть служба (загруженная с отложенным доступом), и если она выдает неисправимое исключение, я не хочу идти дальше, я хочу закрыть Java (я также хотел бы спросить здесь, если это хорошая техника:)).

static final ServiceClass mLazyService;

static {
    try {
        mLazyService = new ServiceClass ();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...