5

我最近问过如何从另一个类中获取唯一的类实例。

如何从 Java 中的另一个类中获取特定的类实例?

所以,我试图让它工作:

我的Application

public class Application
{

    // I will always have only one instance of Application

    private static Application _application;

    // Every instance of Application (one in my case) should have its own View

    private View view;

    // Constructor for new instance of Application

    private Application()
    {
        view = new View();
    }

    // Getter for my unique instance of Application

    public static Application getSharedApplication()
    {
        if (_application == null)
            _application = new Application();
        return _application;
    }

    // Main class

    public static void main(String[] args)
    {
        // So I'm accessing my instance of Application
        Application application1 = getSharedApplication();

        // Here is object reference
        System.out.println(application1);

        // And now I'm accessing the same instance of Application through instance of View
        Application application2 = application1.view.getApplication();

        // Here is object reference
        System.out.println(application2);
    }

}

我的View

public class View
{

    // I'm accessing my instance of Application again

    public static Application application = Application.getSharedApplication();

    // This method should return my unique instance of Application

    public Application getApplication()
    {
        return application;
    }

}

问题是该main方法返回不同的对象引用。

Application@1430b5c
Application@c2a132

我的代码有什么问题?

4

4 回答 4

7

这是发生的事情:

  • 程序首先调用Application application1 = getSharedApplication();
  • 反过来调用调用的静态方法new Application()-该调用需要加载 View 类,该类是Application.
  • View 类被加载,它的静态成员被初始化并运行getSharedApplication();(注意在这个阶段,_application仍然是 null)。这也创造了new Application()一个

您现在有 2 个应用程序实例。

请注意,如果您添加View v = new View();为 main 的第一行,则只有一个 Application 实例(从 View 的静态变量中加载一次)。当你仔细考虑它但不是很直观时,这是有道理的......

于 2012-08-16T18:05:09.417 回答
4

此类问题的一般答案是:使用调试器!例如,您可以在 的构造函数中设置断点Application,运行程序,并在构造函数第二次执行时检查堆栈。

如果你这样做,你会注意到这样的事情:

Application.<init>() line: 21   
Application.getSharedApplication() line: 31 
View.<clinit>() line: 59    
Application.<init>() line: 23   
Application.getSharedApplication() line: 31 

也就是说,视图想要在共享应用程序完全构建之前(并且在后者存储在静态字段中之前)获取共享应用程序。

于 2012-08-16T18:03:15.843 回答
1

如果您更改 View 的初始化,如下所示

public static Application getSharedApplication() {

    if(_application == null)
    {
        _application = new Application();
        view = new View();
    }

您会发现只创建了一个实例。原因是您在 Application 完全初始化之前创建 View 实例。因为第一次请求类时会加载静态变量,所以这种行为正在发生。

无论如何,我了解到永远不要这样做:)谢谢:)

于 2012-08-16T18:31:51.910 回答
0

getSharedApplication() 方法应该使用 synchronized 关键字。否则,两个线程可能会进入第一个 if 语句块并且都创建不同的变量。

我不确定这是否是这里发生的事情。尝试在任何地方添加调试/打印语句,这样您就可以了解实际发生的情况。

于 2012-08-16T18:06:16.120 回答