如何将参数传递给静态初始化块

cvu*_*vue 5 java oop file-io singleton utility-method

我想要做的是将文件(使用Apache poi的excel文件)中的键/值对加载到将用作查找表的静态映射中.一旦加载,表格就不会改变.

public final class LookupTable
{  
   private final static Map<String, String> map;  
   static {
     map = new HashMap<String, String>();
     // should do initialization here
     // InputStream is = new FileInputStream(new File("pathToFile"));
     // not sure how to pass pathToFile without hardcoding it?
   }

   private LookupTable() {
   }

  public static void loadTable(InputStream is) {
    // read table from file
    // load it into map
    map.put("regex", "value");
  }

  public static String getValue(String key) {
    return map.get(key);
  }
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想在静态初始化块中加载映射,但是如何在不对其进行硬编码的情况下传递流?我在使用loadTable静态方法时看到的问题是在调用其他静态方法之前可能没有调用它.

// LookupTable.loadTable(stream);  
LookupTable.getValue("regex"); // null since map was never populated.
Run Code Online (Sandbox Code Playgroud)

有更好的方法吗?

sig*_*ned 5

您使用的任何内容都必须在启动时可以访问。据我所知,您的选择是:

  1. 对路径进行硬编码。出于显而易见的原因,这很糟糕。
  2. 静态变量或静态方法。这有点像先有鸡还是先有蛋的问题。最终它会被硬编码,但至少您可以使用static方法进行搜索。
  3. 使用变量,Java 或环境变量。所以,你会使用一些东西System.getProperty("filename", "/default/filename")。更好,因为它至少可以-D在 JVM 启动时使用环境或参数进行自定义。
  4. 使用ClassLoader getResource*方法。这可能是正确的答案。getResourceAsStream()具体来说,您可能希望在当前线程的 context 上使用该方法ClassLoader Thread.currentThread().getContextClassLoader()。(所以,Thread.currentThread().getContextClassLoader().getResourceAsStream("filename")总共。)ClassLoader然后,它将为您找到您的资源(只要您将其放在您的 中合理的位置CLASSPATH)。


das*_*ght 1

您不能将信息传递到静态初始化块中 - 它们应该独立工作。由于在程序开始执行之前需要知道您计划传递的流,因此您LookupTable应该也能够找到它。例如,这可能是某种为您提供流的配置实用程序。然后你可以像这样编写你的初始化程序:

static {
    InputStream exelStream = MyConfigUtil.getExcelStreamForLookup();
    loadTable(exelStream);
}
Run Code Online (Sandbox Code Playgroud)

据推测,系统中有一个类可以从已知的源获取 Excel 流。源不需要进行硬编码:它可以从配置文件中读取位置,或者从服务器上的预定义网络位置接收数据。在所有情况下,获取 Excel 流的过程都必须在某个地方“触底”,即系统中的某些内容需要能够在没有其他参数的情况下找到它。