Java 如何将参数传递到静态初始化块
我要做的是将文件(使用ApachePOI的excel文件)中的键/值对加载到静态映射中,该静态映射将用作查找表。一旦加载,表将不会更改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
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流的过程都必须从某种意义上说,系统中的某些东西需要能够在没有附加参数的情况下找到它。启动时必须能够访问您使用的任何东西。据我所知,您的选项有:
静态方法进行搜索
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");