public static Properties prop;
private static UnionAuthProperties unionAuthProperties;
private UnionAuthProperties() {
try {
prop = PropertiesUtil.getPropertiesFromClassPath("unionauth.properties");
} catch (Exception e) {
LOG.error("{}",e);
}
}
public static synchronized UnionAuthProperties getInstance() {
if (unionAuthProperties == null) {
unionAuthProperties = new UnionAuthProperties(); #27
}
return unionAuthProperties;
}
private final String URL_REQUEST = prop.getProperty("url.request"); #32
最后一个语句URL_REQUEST导致:
threw exception
java.lang.NullPointerException
at UnionAuthProperties.<init>(UnionAuthProperties.java:32)
at UnionAuthProperties.getInstance(UnionAuthProperties.java:27)
at UnionAuthClient.<init>(UnionAuthClient.java:9)
根据我的知识,实例无论是否为final都是在构造函数[1]之后启动的,而最后的实例必须在构造函数[2]结束之前分配。那么为什么在初始化URL_REQUEST时prop是NULL?
编辑:如果在super()和this(...)完成之后,初始化实例,则应将最终实例REDIRECT_URI初始化为null或空白。但是,这会将REDIRECT_URI打印为REDIRECT_URI:
public class Test {
private static Properties prop;
public static void main(String[] args) {
Test a = new Test();
}
public Test() {
// The following code should run after private final String REDIRECT_URI;
try {
System.out.println();
} catch (Exception e) {}
REDIRECT_URI = "REDIRECT_URI";
System.out.println(REDIRECT_URI);
}
private final String REDIRECT_URI;
}
我还试图像这样改变构造函数:
private UnionAuthProperties() {
prop = new Properties();
}
仍然是NPE。
答案 0 :(得分:1)
http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.5
第1-3项指定调用super()和this()
的显式或隐式变体第4项从上到下说execute instance variable initializers
。
这意味着所有不在构造函数内的final和non-final字段,现在只是初始化新实例的字段。
第5项说执行rest of the body of this constructor
,其中rest
在您的案例中以try { prop = ...
开头。 Rest
表示“没有super()或this()”
因此prop.getProperty("url.request")
在构造函数的其余部分初始化prop
之前执行。
我会将prop
初始化移动到getInstance()函数。
以下是代码执行的顺序(初始化和构造函数代码)
// 1. when class is loaded (because it is `static`) effectively same as public static Properties prop = null;
public static Properties prop;
// 2. when class is loaded; effectively same as unionAuthProperties = null
private static UnionAuthProperties unionAuthProperties;
private UnionAuthProperties() {
try {
// 5. executing constructor code
prop = PropertiesUtil.getPropertiesFromClassPath("unionauth.properties");
} catch (Exception e) {
LOG.error("{}",e);
}
}
public static synchronized UnionAuthProperties getInstance() {
if (unionAuthProperties == null) {
// 3. creating new instance (first only constructor called, assignment is later)
unionAuthProperties = new UnionAuthProperties(); #27
}
return unionAuthProperties;
}
// 4. `execute instance variable initializers` in top to bottom order
// prop is null yet
private final String URL_REQUEST = prop.getProperty("url.request");