how to pass parameter to static initialize block

cvue picture cvue · Apr 3, 2013 · Viewed 10.6k times · Source

What I want to do is load key/value pairs from a file (excel file using Apache poi) into a static map that will be used as a lookup table. Once loaded the table will not change.

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

Ideally I want to load the map within the static initialization block, but how would I pass the stream in without hard coding it? The problem I see using the loadTable static method is it might not be called before calling the other static methods.

// LookupTable.loadTable(stream);  
LookupTable.getValue("regex"); // null since map was never populated.

Is there a better approach to this?

Answer

sigpwned picture sigpwned · Apr 3, 2013

Anything you use will have to be accessible at startup. As far as I know, your options are:

  1. Hard-code the path. This is bad for obvious reasons.
  2. A static variable or static method. This presents a bit of a chicken-and-egg problem; ultimately it gets hard-coded, but at least you can do a search with a static method.
  3. Use a variable, either Java or Environment. So, you'd use something System.getProperty("filename", "/default/filename"). Better because it's at least customizable using the environment or -D parameters at JVM startup.
  4. Use the ClassLoader getResource* methods. This is probably The Right Answer. Specifically, you'll probably want to use the getResourceAsStream() method on the current thread's context ClassLoader Thread.currentThread().getContextClassLoader(). (So, Thread.currentThread().getContextClassLoader().getResourceAsStream("filename") in total.) The ClassLoader will then find your resource for you (as long as you put it somewhere sane in your CLASSPATH).