2012-08-16 72 views
5

我问过最近从另一个类获取唯一类的实例。相同(?)对象的不同对象引用

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方法返回不同对象引用。

[email protected] 
[email protected] 

我的代码有什么问题?

+0

它使用一个单身人士和其他形式的全局状态,这就是不对的地方。 – 2012-08-16 18:02:46

+0

当你需要单身人士时,为什么不使用枚举? – 2012-08-16 18:06:12

回答

7

这里是发生了什么:

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

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

请注意,如果您添加View v = new View();作为main的第一行,那么您只有一个Application实例(从View的静态变量中加载一次)。当你认真思考但不太直观时,这是有道理的...

+0

美丽。这个例子应该放在“为什么辛格尔顿几乎总是一个坏主意”的页面上! – Jochen 2012-08-16 18:07:06

+0

全局状态(静态变量)很难推理,特别是当存在循环引用时! – assylias 2012-08-16 18:08:57

+1

单身人士并不是一个坏主意,但是他们可能实施得不好,就像他们在这里一样。 – 2012-08-16 18:43:28

4

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

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

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

也就是说,认为想要得到共享的应用程序之前,应用程序共享已经完全构造(和之前后者存储在静态字段中)。

0

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

我不确定这是发生在这里的事情。尝试在所有地方添加调试/打印语句,以便可以追踪真正发生的事情。

+2

在这个例子中只有一个线程。 – assylias 2012-08-16 18:06:54

+0

@assylias我知道,但如果方法不同步,他以后会问。 – 2012-08-16 18:11:03

+0

你提出一个公正的观点 - 我只是说它不是问题的原因。 – assylias 2012-08-16 18:12:52

1

如果更改像下面

public static Application getSharedApplication() { 

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

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

无论如何,我了解到,从来没有做到这一点:)谢谢:)

+0

嗯,那有效! :) – 2012-08-16 19:33:37