Algunas personas han preguntado: ¿cómo puede el singleton devolver un puntero nulo?
Estoy respondiendo esa pregunta. (No puedo responder en un comentario porque necesito publicar el código).
Puede devolver nulo entre dos eventos: (1) se carga la clase y (2) se crea el objeto de esta clase. Aquí hay un ejemplo:
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);
}
}
Ejecutemos el código:
$ javac A.java
$ java A
x:X@a63599 y:Y@9036e
x:null y:null
La segunda línea muestra que Y.xinstance y X.yinstance son nulos ; son nulos porque las variables X.xinstance y Y.yinstance se leyeron cuando eran nulas.
¿Se puede arreglar esto? Si,
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);
}
}
y este código no muestra anomalía:
$ javac A.java
$ java A
x:X@1c059f6 y:Y@152506e
x:X@1c059f6 y:Y@152506e
PERO esto no es una opción para el Application
objeto Android : el programador no controla el momento en que se crea.
Una vez más: la diferencia entre el primer ejemplo y el segundo es que el segundo ejemplo crea una instancia si el puntero estático es nulo. Pero un programador no puede crear el objeto de la aplicación de Android antes de que el sistema decida hacerlo.
ACTUALIZAR
Un ejemplo más desconcertante donde los campos estáticos inicializados resultan ser 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());
}
}
Y obtienes:
$ javac Main.java
$ java Main
first: FIRST second: SECOND
first: <FIRST> second: <SECOND>
first: nullFIRSTnull second: nullSECONDnull
Tenga en cuenta que no puede mover la declaración de variable estática una línea hacia arriba, el código no se compilará.
<application>
nodo del archivo AndroidManifest.xml incluir la siguiente definición de atributo:android:name="MyApp"
. MyApp debe estar bajo el mismo paquete que sus referencias de manifiesto.