Java-如何选择可用路径以在静态块中加载文件?

时间:2018-11-02 08:39:23

标签: java io

我的类中有一个静态块,因此,当类加载器加载类定义时,会从该静态块中调用一个方法。该方法的目的是从可用路径之一加载配置。我希望使用第一个可用路径。

有2个配置文件(metrics_config.jsonmetrics_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 :(得分:2)

解决方案实际上是不这样做。没有static code blocks或其他类初始化代码,因为诸如IO(不使用类加载器)之类的环境问题,操作失败的机率很高。

  • 确保良好的错误处理实在太困难了。 Checked exceptions, include IOException, may not propagate out of them,这意味着全部 IO代码中的错误处理必须是自包含的。
  • 这使得使用依赖注入的单元测试非常困难。
  • The order that static blocks in different classes are executed is not obvious and can change if you refactor your code。如果您的代码很复杂,那么这两个static块之间的依赖就很难正确解决。正确执行IO很复杂。
  • static块在持有锁定的同时执行。如果您的static直接或间接尝试执行任何多线程操作,则可能导致死锁。例如,通过using streams。避免此类问题的唯一方法是将代码保持在非常简单块中。如前所述,IO代码很复杂。它不可避免地涉及到以复杂且不明显的方式委派给其他类(封装和信息隐藏是一种功能,而不是错误)。您可以确定封装的代码中没有没有会导致死锁吗?
  • 而且重要的是,在卸载相应的类加载器之前,不会对静态对象引用进行垃圾回收。因此,当引用外部资源时,由于可能的内存泄漏而造成的影响可能会很严重。

相反,将配置文件读入您​​的main方法或从中调用的方法。

答案 1 :(得分:1)

您可以使用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);
    }
}

在最佳情况下,这意味着仅需要检查两条路径,但是在最坏情况下,仍然需要检查所有路径。

为避免代码重复,最好创建一个单独的方法来获取正确的文件。

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));
}