2012-08-16 44 views
5

Tôi đã hỏi về việc nhận cá thể lớp duy nhất từ ​​một lớp khác gần đây.Các tham chiếu đối tượng khác nhau cho cùng một đối tượng (?)

(How to get specific instance of class from another class in Java?)

Vì vậy, tôi đang cố gắng để làm cho nó hoạt:

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

} 

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

} 

Vấn đề là main phương thức trả về khác nhau tham chiếu đối tượng.

[email protected] 
[email protected] 

Có gì sai với mã của tôi?

+0

Nó sử dụng một đơn và các hình thức khác của nhà nước toàn cầu, đó là những gì là sai với nó. –

+0

Tại sao không sử dụng enums khi bạn cần Singletons.? –

Trả lời

7

Đây là những gì sẽ xảy ra:

  • chương trình đầu tiên gọi Application application1 = getSharedApplication();
  • mà lần lượt gọi phương thức tĩnh trong đó kêu gọi new Application() - gọi mà cần phải tải các lớp View, mà là một thành viên của Application.
  • lớp Chế độ xem được tải và thành viên tĩnh của nó được khởi tạo và chạy getSharedApplication(); (lưu ý rằng ở giai đoạn này, _application vẫn là giá trị rỗng). Điều đó tạo ra một new Application() quá

Bây giờ bạn có 2 trường hợp Ứng dụng.

Lưu ý rằng nếu bạn thêm View v = new View(); làm dòng đầu tiên của chính, bạn chỉ có một phiên bản Ứng dụng (được tải một lần từ biến tĩnh của Chế độ xem). Điều đó có ý nghĩa khi bạn suy nghĩ kỹ về nó nhưng không phải là rất trực quan ...

+0

Đẹp. Ví dụ này nên đi trên trang cho "Tại sao Singleton gần như luôn luôn là một ý tưởng tồi"! – Jochen

+0

Trạng thái toàn cầu (biến tĩnh) khó có thể giải thích được, đặc biệt khi có các tham chiếu chu kỳ! – assylias

+1

Singletons không phải là một ý tưởng tồi, nhưng chúng có thể được thực hiện kém, vì chúng ở đây. –

4

Câu trả lời chung cho các câu hỏi như vậy là: Sử dụng trình gỡ lỗi! Ví dụ, bạn có thể thiết lập một điểm ngắt trong hàm tạo của Application, chạy chương trình của bạn và kiểm tra ngăn xếp khi hàm tạo thi hành lần thứ hai.

Nếu bạn làm điều này, bạn sẽ lưu ý một cái gì đó như thế này:

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

Đó là, quan điểm muốn để có được những ứng dụng chia sẻ trước khi ứng dụng chia sẻ đã được xây dựng hoàn toàn (và trước khi chúng được lưu trữ trong trường tĩnh).

0

Phương thức getSharedApplication() nên sử dụng từ khóa được đồng bộ hóa. Nếu không, hai luồng có thể nhập khối câu lệnh if đầu tiên và cả hai tạo các biến khác nhau.

Tôi không chắc đó có phải là những gì đang xảy ra ở đây hay không. Thử thêm các câu lệnh debug/print ở khắp mọi nơi để bạn có thể theo dõi những gì đang thực sự xảy ra.

+2

Chỉ có một chuỗi trong ví dụ này. – assylias

+0

@assylias Tôi biết, nhưng anh ấy yêu cầu sự cố sau này nếu phương pháp không được đồng bộ hóa. –

+0

Bạn đưa ra một điểm công bằng - Tôi chỉ nói rằng đó không phải là nguyên nhân của vấn đề. – assylias

1

Nếu bạn thay đổi khởi của Xem như dưới đây

public static Application getSharedApplication() { 

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

Bạn sẽ tìm thấy chỉ một trường hợp được nhận được tạo ra. Lý do là bạn đang tạo Xem cá thể trước khi Ứng dụng được khởi tạo hoàn toàn. Bởi vì các biến tĩnh được nạp khi lớp được yêu cầu lần đầu tiên nên hành vi này đang xảy ra.

Dù sao tôi đã học mà không bao giờ làm điều này :) cảm ơn :)

+0

Hm, nó hoạt động! :) –

Các vấn đề liên quan