Java - как выбрать доступный путь для загрузки файла в статическом блоке? - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть статический блок в моем классе, так что когда загрузчик классов загружает определение класса - метод вызывается из этого статического блока. Целью метода является загрузка конфигурации с одного из доступных путей. Я хочу использовать первый доступный путь.

Существует 2 файла конфигурации (metrics_config.json, metrics_config_new.json), и каждый из них может находиться в одном из 2 путей:

private static final File CONFIG_FILE_1 = new File("file:///dest1/config/metrics_config.json");
private static final File CONFIG_FILE_2 = new File("file:///dest2/config/metrics_config.json");

private static final File CONFIG_FILE_3 = new File("file:///dest1/config/metrics_config_new.json");
private static final File CONFIG_FILE_4 = new File("file:///dest2/config/metrics_config_new.json");

Как мне пройти только один путь, который в настоящее время доступен для метода? Я полагаю, это может выглядеть примерно так:

static {
    // choose 1st file's path
    if (CONFIG_FILE_1.exists() && CONFIG_FILE_1.isFile()) {
        loadConfiguration(CONFIG_FILE_1);
    }
    if (CONFIG_FILE_2.exists() && CONFIG_FILE_2.isFile()) {
         loadConfiguration(CONFIG_FILE_2);
    }
    // choose 2nd file's path
    if (CONFIG_FILE_3.exists() && CONFIG_FILE_3.isFile()) {
         loadConfiguration(CONFIG_FILE_3);
    }
    if (CONFIG_FILE_4.exists() && CONFIG_FILE_4.isFile()) {
         loadConfiguration(CONFIG_FILE_4);
    }
}

Недостатком моего текущего решения является то, что он будет проверять оба пути для первого файла и для второго файла. Как правильно определить путь к методу loadConfiguration?

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Решение этого на самом деле не в том, чтобы сделать это. Не используйте static кодовые блоки или другой код инициализации класса, выполняйте операции, которые с большой вероятностью дают сбой из-за проблем среды, таких как IO (кроме использования загрузчика классов).

Также

  • Обеспечение хорошей обработки ошибок при этом просто слишком сложно. Проверенные исключения, включая IOException, могут не распространяться из них , что означает все , обработка ошибок в вашем коде ввода-вывода должна быть автономной.
  • Очень затрудняет юнит-тестирование с использованием Dependency Injection.
  • Порядок выполнения блоков static в разных классах неочевиден и может измениться, если вы реорганизуете код . Это затрудняет получение зависимостей между этими static блоками , если ваш код сложен . Правильно выполнить IO сложно.
  • Блоки static выполняются, пока удерживается блокировка. Это может вызвать взаимоблокировку, если ваш static блок напрямую или косвенно пытается выполнить какую-либо многопоточность. Например, используя потоки . Единственный способ избежать таких проблем - сохранить код в блоке очень простым . Как я уже говорил, IO-код сложен. Это неизбежно влечет за собой делегирование другим классам сложным и неочевидным способом (инкапсуляция и сокрытие информации - это особенность, а не ошибка). Можете ли вы быть уверены, что нет инкапсулированного кода приведет к тупику?
  • И, что важно, ссылка на статический объект не будет собираться мусором, пока не загрузится соответствующий загрузчик классов. Таким образом, когда ссылка относится к внешнему ресурсу, воздействие из-за возможной утечки памяти может быть серьезным.

Вместо этого переместите чтение файла конфигурации в ваш метод main или вызванный из него метод.

0 голосов
/ 02 ноября 2018

Вы можете использовать else if, чтобы сделать что-то вроде этого:

static {
    // choose 1st file's path
    if (CONFIG_FILE_1.exists() && CONFIG_FILE_1.isFile()) {
        loadConfiguration(CONFIG_FILE_1);
    }
    else if (CONFIG_FILE_2.exists() && CONFIG_FILE_2.isFile()) {
         loadConfiguration(CONFIG_FILE_2);
    }
    // choose 2nd file's path
    if (CONFIG_FILE_3.exists() && CONFIG_FILE_3.isFile()) {
         loadConfiguration(CONFIG_FILE_3);
    }
    else if (CONFIG_FILE_4.exists() && CONFIG_FILE_4.isFile()) {
         loadConfiguration(CONFIG_FILE_4);
    }
}

В лучшем случае это будет означать, что нужно проверить только 2 пути, однако в худшем случае все пути еще нужно проверить.

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

public static File fetchConfigFile(file1, file2) {
    if (file1.exists() && file1.isFile()) {
        return file1;
    }
    else if (file2.exists() && file2.isFile()) {
         return file2;
    }
    // Be aware: returning null might not be what you want. 
    return null;
}

А чем блок static можно упростить до этого:

static {
    loadConfiguration(fetchConfigFile(CONFIG_FILE_1, CONFIG_FILE_2));
    loadConfiguration(fetchConfigFile(CONFIG_FILE_3, CONFIG_FILE_4));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...