Using Application context everywhere?

后端 未结 9 885
难免孤独
难免孤独 2020-11-22 01:52

In an Android app, is there anything wrong with the following approach:

public class MyApp extends android.app.Application {

    private static MyApp instan         


        
9条回答
  •  -上瘾入骨i
    2020-11-22 01:55

    Some people have asked: how can the singleton return a null pointer? I'm answering that question. (I cannot answer in a comment because I need to post code.)

    It may return null in between two events: (1) the class is loaded, and (2) the object of this class is created. Here's an example:

    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);
        }
    }
    

    Let's run the code:

    $ javac A.java 
    $ java A
    x:X@a63599 y:Y@9036e
    x:null y:null
    

    The second line shows that Y.xinstance and X.yinstance are null; they are null because the variables X.xinstance ans Y.yinstance were read when they were null.

    Can this be fixed? Yes,

    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);
        }
    }
    

    and this code shows no anomaly:

    $ javac A.java 
    $ java A
    x:X@1c059f6 y:Y@152506e
    x:X@1c059f6 y:Y@152506e
    

    BUT this is not an option for the Android Application object: the programmer does not control the time when it is created.

    Once again: the difference between the first example and the second one is that the second example creates an instance if the static pointer is null. But a programmer cannot create the Android application object before the system decides to do it.

    UPDATE

    One more puzzling example where initialized static fields happen to be 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());
        }
    }
    

    And you get:

    $ javac Main.java
    $ java Main
    first: FIRST second: SECOND
    first:  second: 
    first: nullFIRSTnull second: nullSECONDnull
    

    Note that you cannot move the static variable declaration one line upper, the code will not compile.

提交回复
热议问题