最终实例是在构造函数之前启动和分配的吗?
is final instance initiated and assigned before constructor?
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还是非final的实例都是在constructor [1] while the final ones have to be assigned before the end of constructor [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。
http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.5
第 1-3 项指定调用 super() 和 this() 的显式或隐式变体
第 4 项从上到下说 execute instance variable initializers
。
这意味着所有不在构造函数内的最终和非最终字段,现在只初始化新实例的字段。
项目 5 说执行 rest of the body of this constructor
,其中 rest
在您的案例中以 try { prop = ...
开头。 Rest
表示 "without super() or 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");
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还是非final的实例都是在constructor [1] while the final ones have to be assigned before the end of constructor [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。
http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.5
第 1-3 项指定调用 super() 和 this() 的显式或隐式变体
第 4 项从上到下说 execute instance variable initializers
。
这意味着所有不在构造函数内的最终和非最终字段,现在只初始化新实例的字段。
项目 5 说执行 rest of the body of this constructor
,其中 rest
在您的案例中以 try { prop = ...
开头。 Rest
表示 "without super() or 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");