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

Java 如何将参数传递到静态初始化块,java,oop,file-io,singleton,utility-method,Java,Oop,File Io,Singleton,Utility Method,我要做的是将文件(使用ApachePOI的excel文件)中的键/值对加载到静态映射中,该静态映射将用作查找表。一旦加载,表将不会更改 public final class LookupTable { private final static Map<String, String> map; static { map = new HashMap<String, String>(); // should do initializati

我要做的是将文件(使用ApachePOI的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);
  }
}

有更好的方法吗?

是的,有更好的方法,使用Factory design模式初始化对象,然后再使用它:


这可能是使用延迟加载映射的情况

但是在第一次调用
getValue()
之前,需要设置
inputFileName
。这将在应用程序的初始化代码中完成。(也可以使用静态方法进行设置。)

这指出了延迟加载的优点。在第一次调用
getValue()
之前,不必让文件名可用。使用静态初始值设定项时,必须获取存储在类外部某处的文件名,以便在类加载时(但在静态字段初始化之后)可以使用该文件名加载数据

 public static String inputFileName = null;

 public static String getValue(String key) {
    if (map == null) {
        map = = new HashMap<String, String>();
        // open the file using 'inputFileName'
        loadTable(InputStream is);
    }
    return map.get(key);
  }
公共静态字符串inputFileName=null;
公共静态字符串getValue(字符串键){
if(map==null){
map==新的HashMap();
//使用“inputFileName”打开文件
加载表(输入流为);
}
返回map.get(key);
}
如果您的代码是多线程的,请告诉我,我将对同步问题进行评论

备选方案


您还可以使用Spring注入映射并在其他类中构建它,例如,
MapBuilder

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

static {
    InputStream exelStream = MyConfigUtil.getExcelStreamForLookup();
    loadTable(exelStream);
}

据推测,系统中有一个类可以从已知的源获取Excel流。源不需要硬编码:它可以从配置文件读取位置,或从服务器上预定义的网络位置接收数据。在所有情况下,获取Excel流的过程都必须从某种意义上说,系统中的某些东西需要能够在没有附加参数的情况下找到它。

启动时必须能够访问您使用的任何东西。据我所知,您的选项有:

  • 对路径进行硬编码。这显然是不好的
  • 一个静态变量或静态方法。这会带来一点鸡毛蒜皮的问题;最终它会被硬编码,但至少你可以用
    静态方法进行搜索
  • 使用Java或环境变量。因此,最好使用
    System.getProperty(“filename”,“/default/filename”)
    。因为它至少可以在JVM启动时使用环境或
    -d
    参数进行自定义
  • 使用
    ClassLoader
    getResource*
    方法。
    这可能是正确的答案。具体来说,您可能希望在当前线程的上下文
    ClassLoader
    上使用该方法(因此,
    thread.currentThread().getContextClassLoader().getResourceAsStream(“文件名”)
    )然后,
    ClassLoader
    将为您找到资源(只要您将其放在
    CLASSPATH
    中某个合理的位置)

  • 尝试使用System.getProperty()并在命令行中用-D传递参数

    static String prop;
    
    static {
        prop = System.getProperty("java.home");
    }
    
    public static void main(String... args) {
    
        System.out.println(prop);
    }
    

    这并不是直接回答您的问题,但我不明白为什么
    map
    必须是静态的。您可以将
    map
    更改为非静态,并将构造函数更改为
    public LookupTable(File File File){…fill map…}
    。如果您有不同的excel文件,那么您甚至可以拥有该类的许多实例;现在可能不是这样,但它将“证明”您的代码。

    如果它适合您的情况,我建议使用一个

    public enum LookupTable {
    
        INSTANCE(FileManager.getFileName());
    
        LookupTable(String fileName){
            props = new HashMap<String,String>();
            //Read from excel and fill the hashmap
        }
    
        private final Map<String, String> props;
    
        public String getMapValue(String key){
            return props.get(key);
        }   
    }
    
    这将按顺序调用这些方法

    • 从filemanager类获取文件名,该类根据您的需要进行参数化
    • 调用构造函数(它是私有的)并从excel文件加载属性
    • 键的getMapValue并返回

    后续调用LookupTable.INSTANCE.getMapValue(“mysecondkey”)将只在实例预先初始化时调用getMapValue。

    如何
    getValue
    知道
    InputStream
    ?接受DasLinkedLight答案,因为它回答了原始问题。考虑过这个问题后,我可能会重新设计并使用ToToTo2答案。
    public enum LookupTable {
    
        INSTANCE(FileManager.getFileName());
    
        LookupTable(String fileName){
            props = new HashMap<String,String>();
            //Read from excel and fill the hashmap
        }
    
        private final Map<String, String> props;
    
        public String getMapValue(String key){
            return props.get(key);
        }   
    }
    
    LookupTable.INSTANCE.getMapValue("mykey");