有些人问过:单例模式如何返回空指针?
我正在回答这个问题。(我不能在评论中回答,因为我需要发布代码。)
它可能在两个事件之间返回 null:(1)加载类,和(2)创建这个类的对象。以下是一个例子:
class X {
static X xinstance;
static Y yinstance = Y.yinstance;
X() {xinstance=this;}
}
class Y {
static X xinstance = X.xinstance;
static Y yinstance;
Y() {yinstance=this;}
}
public class A {
public static void main(String[] p) {
X x = new X();
Y y = new Y();
System.out.println("x:"+X.xinstance+" y:"+Y.yinstance);
System.out.println("x:"+Y.xinstance+" y:"+X.yinstance);
}
}
让我们运行这段代码:
$ javac A.java
$ java A
x:X@a63599 y:Y@9036e
x:null y:null
第二行显示Y.xinstance和X.yinstance都是null;它们是空的,因为在读取变量X.xinstance和Y.yinstance时它们是空的。
这可以修复吗?可以,
class X {
static Y y = Y.getInstance();
static X theinstance;
static X getInstance() {if(theinstance==null) {theinstance = new X();} return theinstance;}
}
class Y {
static X x = X.getInstance();
static Y theinstance;
static Y getInstance() {if(theinstance==null) {theinstance = new Y();} return theinstance;}
}
public class A {
public static void main(String[] p) {
System.out.println("x:"+X.getInstance()+" y:"+Y.getInstance());
System.out.println("x:"+Y.x+" y:"+X.y);
}
}
这段代码没有异常:
$ javac A.java
$ java A
x:X@1c059f6 y:Y@152506e
x:X@1c059f6 y:Y@152506e
但是对于Android Application
对象来说,这不是一种选择:程序员无法控制其创建的时间。
再次强调:第一个示例和第二个示例之间的区别在于第二个示例会在静态指针为空时创建一个实例。但是程序员无法在系统决定创建它之前创建the Android应用程序对象。
更新
另一个令人困惑的示例,其中已初始化的静态字段恰好为null
。
Main.java:
enum MyEnum {
FIRST,SECOND;
private static String prefix="<", suffix=">";
String myName;
MyEnum() {
myName = makeMyName();
}
String makeMyName() {
return prefix + name() + suffix;
}
String getMyName() {
return myName;
}
}
public class Main {
public static void main(String args[]) {
System.out.println("first: "+MyEnum.FIRST+" second: "+MyEnum.SECOND);
System.out.println("first: "+MyEnum.FIRST.makeMyName()+" second: "+MyEnum.SECOND.makeMyName());
System.out.println("first: "+MyEnum.FIRST.getMyName()+" second: "+MyEnum.SECOND.getMyName());
}
}
然后你会得到:
$ javac Main.java
$ java Main
first: FIRST second: SECOND
first: <FIRST> second: <SECOND>
first: nullFIRSTnull second: nullSECONDnull
请注意,您不能将静态变量声明提前一行,否则代码将无法编译。
<application>
节点,包括以下属性定义:android:name="MyApp"
。 MyApp需要在与您的清单引用相同的包下。 - Matt Huggins