gpt4 book ai didi

java - NPE 被抛出将键/值对加载到 java.util.Properties 对象中

转载 作者:行者123 更新时间:2023-12-02 04:25:28 28 4
gpt4 key购买 nike

我遇到了一个关于将键/值对从流加载到 java.util.Properties 对象中时无法自己回答的问题。我正在处理的 Foo servlet 类中有一个方法调用 loadProperties() 方法。在情况 1) 中检索所选键的值有效,但在情况 2) loadProperties().getProperty("bar") 中抛出 NullPointerException。我不知道为什么 NPE 被抛出。我忘记添加,但 loadProperties() 在同一 Foo 实例中调用了多次。

案例1)

public class Foo extends HttpServlet {
private InputStream is = null;

private Properties loadProperties() {
Properties p = new Properties();
is = Foo.class.getClassLoader().getResourceStream("/com/test/bar.properties");
p.load(is);
return p;
}
}

案例2)

public class Foo extends HttpServlet {
private final InputStream is = Foo.class.getClassLoader().getResourceStream("/com/test/bar.properties);

private Properties loadProperties() {
Properties p = new Properties();
p.load(is);
return p;
}
}

调用loadProperties()

public class Foo extends HttpServlet {
private Properties loadProperties() { .... }

private void doSomething() {
PrintStream ps = new PrintStream(new FileOutputStream(loadProperties().getProperty("bar"))); // NPE was thrown in the case 2)
is.close();
}

private void doSomething2() {
PrintStream ps = new PrintStream(new FileOutputStream(loadProperties().getProperty("xyz")));
is.close();
}
}

[更新]

安迪回答了我的问题。当他问我 loadProperties() 是否多次调用时,我检查了 Foo 类的长行,唉!我发现它在 doPost 方法中无意中被调用了一次。

public class Foo extends HttpServlet {
protected void doPost(...) {
loadProperties();

callDoSomething();
callDoSomething2();
}

private Properties loadPropeties() {
....
}

private void doSomething() {
....
}

private void doSomething2() {
....
}
}

最佳答案

在情况 2 中,您每次调用 loadProperties 时都会尝试重复使用相同的流。方法。

可能在第一次调用时正确工作:Properties.load将消耗流中的所有数据,直到到达末尾,然后返回所有 Property它已加载。

(“可能”是因为下面提到的线程安全问题)。

但是,在随后调用 loadProperties() 时(情况 2),没有什么可读取的 - 流中的所有数据都已被消耗。除非您明确地倒回流(您甚至可能无法执行此操作,具体取决于返回的 InputStream 的特定子类),否则您将不再有任何数据可供读取。

但是,情况 2 还存在另一个问题,这意味着您不应尝试倒带流:它不是线程安全的。如果两个线程尝试调用loadProperties()同时,我不想猜测会发生什么。你可能只会胡说八道。

Properties.load(InputStream) 的 Javadoc没有说明任何关于同步传递的 InputStream 的方法。因此,您应该避免陷入线程不安全代码的情况 - 在情况 1 中,通过创建一个新的 InputStream 来避免这种情况。对于每次调用。

我假设您试图避免多次重新读取属性。我建议加载Properties在类之外并将它们作为构造函数参数注入(inject):

class Foo extends HttpServlet {
private final Properties properties;

Foo(Properties properties) {
this.properties = checkNotNull(properties);
}

private void doSomething() {
PrintStream ps = new PrintStream(new FileOutputStream(properties.getProperty("bar")));
// ...
}

这样,如果您有 Foo 的实例,它具有有效的 Properties ;您不会等待执行将触发属性加载的特定代码路径,并导致加载失败。

它还使代码更易于测试 - 您不再依赖从文件加载的属性 - 它可以来自任何地方。

关于java - NPE 被抛出将键/值对加载到 java.util.Properties 对象中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32237150/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com