Alcune persone hanno chiesto: come può il singleton restituire un puntatore nullo?
Sto rispondendo a questa domanda. (Non posso rispondere in un commento perché devo inserire il codice.)
Può restituire null tra due eventi: (1) la classe viene caricata e (2) viene creato l'oggetto di questa classe. Ecco un esempio:
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);
}
}
Eseguiamo il codice:
$ javac A.java
$ java A
x:X@a63599 y:Y@9036e
x:null y:null
La seconda riga mostra che Y.xinstance e X.yinstance sono null ; sono nulli perché le variabili X.xinstance e Y.yinstance sono state lette quando erano nulle.
Questo può essere risolto? Sì,
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);
}
}
e questo codice non mostra anomalie:
$ javac A.java
$ java A
x:X@1c059f6 y:Y@152506e
x:X@1c059f6 y:Y@152506e
MA questa non è un'opzione per l' Application
oggetto Android : il programmatore non controlla l'ora in cui viene creato.
Ancora una volta: la differenza tra il primo esempio e il secondo è che il secondo esempio crea un'istanza se il puntatore statico è nullo. Ma un programmatore non può creare l' oggetto dell'applicazione Android prima che il sistema decida di farlo.
AGGIORNARE
Un altro esempio sconcertante in cui si trovano i campi statici inizializzati 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());
}
}
E ottieni:
$ javac Main.java
$ java Main
first: FIRST second: SECOND
first: <FIRST> second: <SECOND>
first: nullFIRSTnull second: nullSECONDnull
Si noti che non è possibile spostare la dichiarazione della variabile statica di una riga in alto, il codice non verrà compilato.
<application>
nodo del file AndroidManifest.xml per includere la seguente definizione di attributo:android:name="MyApp"
. MyApp deve trovarsi nello stesso pacchetto a cui fa riferimento il tuo manifest.