【问题标题】:Different object references for the same(?) object相同(?)对象的不同对象引用
【发布时间】:2012-08-13 03:14:27
【问题描述】:

我最近询问了从另一个类获取唯一类实例的问题。

(How to get specific instance of class from another class in 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

我的代码有什么问题?

【问题讨论】:

  • 它使用单例和其他形式的全局状态,这就是它的问题。
  • 当你需要单例时为什么不使用枚举?

标签: java model-view-controller singleton object-reference


【解决方案1】:

如果你像下面这样改变 View 的初始化

public static Application getSharedApplication() {

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

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

无论如何我都知道永远不要这样做:)谢谢:)

【讨论】:

    【解决方案2】:

    会发生什么:

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

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

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

    【讨论】:

    • 美丽。这个例子应该出现在“为什么单例几乎总是一个坏主意”的页面上!
    • 全局状态(静态变量)很难推理,尤其是当有循环引用时!
    • Singleton 不是一个坏主意,但它们的实现可能很差,就像它们在这里一样。
    【解决方案3】:

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

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

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • @assylias 我知道,但如果方法不同步,他稍后会自找麻烦。
      • 你说得很对 - 我只是说这不是问题的原因。
      猜你喜欢
      • 1970-01-01
      • 2015-03-30
      • 2014-12-24
      • 1970-01-01
      • 2015-08-11
      • 2012-04-23
      • 1970-01-01
      • 2018-01-17
      相关资源
      最近更新 更多