Có phải thực tế xấu để tạo ra các đối tượng mới mà không lưu trữ chúng?


23

Tôi đã thấy các đối tượng được tạo bằng mã Java mà không lưu trữ một tham chiếu đến đối tượng. Ví dụ: trong một plugin nhật thực tôi đã thấy SWT Shell được tạo như vậy:

new Shell();

Đối tượng Shell mới này không được lưu trữ trong một biến, nhưng sẽ vẫn được tham chiếu cho đến khi cửa sổ bị loại bỏ [tôi tin?] Xảy ra theo mặc định khi cửa sổ được đóng.

Có phải thực tế xấu khi tạo các đối tượng như thế này mà không lưu trữ một tài liệu tham khảo đến chúng? Hay là thư viện được thiết kế kém? Điều gì xảy ra nếu tôi không cần tài liệu tham khảo mà chỉ muốn "tác dụng phụ" của đối tượng? Tôi có nên lưu trữ một tài liệu tham khảo dù sao?

CẬP NHẬT:

Phải thừa nhận, ví dụ trên của tôi là kém. Mặc dù tôi đã thấy các phần tử UI được tạo như thế này, nhưng việc tạo một SWT Shell như thế này có thể là vô nghĩa vì bạn cần gọi phương thức mở trên ví dụ Shell. Có các ví dụ tốt hơn được cung cấp bởi aix, chẳng hạn như sau trong hướng dẫn đồng thời Java :

(new HelloThread()).start();

Thực tiễn này được nhìn thấy trong nhiều bối cảnh, vì vậy các câu hỏi vẫn còn. Có phải là thực hành tốt?


2
Điều gì sẽ là điểm lưu trữ tài liệu tham khảo?
Daniel R Hicks

(Nó có lẽ sẽ tốt hơn, từ một quan điểm về khái niệm trên, có một phương pháp tĩnh như Shell.createTopLevelShell()hoặc bất cứ điều gì, vs sử dụng một constructor trong trường hợp này Nhưng về mặt chức năng có rất ít sự khác biệt..)
Daniel R Hicks

Đây có phải là câu hỏi về thực hành tạo đối tượng mà không cần tham khảo chúng, tạo các lớp yêu cầu thực hành này hay cụ thể là về cách SWT sử dụng loại mô hình này?
StriplingWar Warrior

1
Các đối tượng SWT phải là dispose()d: Quy tắc 1: Nếu bạn đã tạo nó, bạn loại bỏ nó. eclipse.org/articles/swt-design-2/swt-design-2.html
jbindel

2
Tôi sẽ sử dụng một biến để giữ một tham chiếu cho mục đích gỡ lỗi. Nếu bạn có một điểm dừng trong phương thức này thì bạn có thể lấy trình gỡ lỗi để truy vấn đối tượng thông qua biến cục bộ. Không có tài liệu tham khảo tôi chắc chắn là có thể nhưng có lẽ khó hơn rất nhiều.
Martin York

Câu trả lời:


12

Có một yếu tố sở thích cá nhân cho vấn đề này, nhưng tôi nghĩ rằng việc không lưu trữ tài liệu tham khảo không nhất thiết là một thực tiễn xấu.

Hãy xem xét ví dụ giả thuyết sau:

new SingleFileProcessor().process(file);

Nếu một đối tượng bộ xử lý mới cần được tạo cho mọi tệp và không cần thiết sau process()cuộc gọi, sẽ không có điểm nào trong việc lưu trữ một tham chiếu đến nó.

Đây là một ví dụ khác, được lấy từ hướng dẫn đồng thời Java :

(new HelloThread()).start();

Tôi đã thấy rất nhiều ví dụ khác khi tài liệu tham khảo không được lưu trữ và nó đọc hoàn toàn tốt cho mắt tôi, chẳng hạn như:

String str = new StringBuilder().append(x).append(y).append(z).toString();

(Đối StringBuildertượng không được lưu giữ.)

Có những mô hình tương tự liên quan đến common.lang's HashCodeBuilderet al.


2
@BalusC: Với sự tôn trọng, tôi không thấy điều gì làm cho nó tanh và theo cách nào thì phương pháp nhà máy tốt hơn (tôi giả sử ví dụ của bạn tương tự như của tôi, và getInstance()là một nhà máy chứ không phải là một người độc thân).
NPE

Tùy thuộc vào nhà máy có sử dụng singleton hay không. Người gọi của nhà máy không nên nghĩ về nó quá nhiều.
Donal Fellows

Trong ví dụ của bạn, đối tượng FileProcessor (có lẽ) không cần thiết sau khi câu lệnh hoàn thành, trong khi trong ví dụ của OP, đối tượng Shell là (dưới vỏ bọc) được tham chiếu bởi một đối tượng khác và tham chiếu đó (và do đó đối tượng Shell) vẫn tồn tại bên ngoài thời hạn của tuyên bố.
Daniel R Hicks

@BalusC: FileProcessor có thể có các phương thức bổ sung để thay đổi hành vi của process.
kevin cline

7

Nếu bạn không cần một tham chiếu đến đối tượng đã tạo, thì đừng giữ tham chiếu. Nó đơn giản như vậy.


5

Nói chung, đó là cách thực hành tốt để phát hành tài liệu tham khảo nhanh nhất có thể. Tôi thấy không có sự khác biệt giữa:

HelloThread thread = new HelloThread();
thread.start();
// where thread is never used for the rest of the method

(new HelloThread()).start();

Đối với mã có liên quan, bạn chỉ cần tránh sử dụng tên biến, đó có thể là một điều tích cực. Trình biên dịch JIT thường đủ thông minh để nhận ra nó có thể thu thập luồng sau khi sử dụng lần cuối, do đó có lẽ không có sự khác biệt nào từ quan điểm hiệu năng.

Vấn đề thực sự duy nhất cần tránh là Mã trong Mô hình chống xây dựng , nhưng nó không giống như những gì bạn đang hỏi về.


3

Điều này có thể xấu nếu bạn đang sử dụng SWT, bởi vì ở đó bạn phải tự dọn dẹp (gọi phương thức dispose ()). Nhưng đối với các lớp khác (không phải SWT) thì không sao.

Đây là một bài viết về Quản lý tài nguyên hệ điều hành


Tài liệu tham khảo thông tư không ngăn các đối tượng khỏi rác được thu thập trong Java. Bất kỳ máy ảo Java hiện đại nào cũng xác định xem các đối tượng có thể truy cập được hay không dựa trên việc chúng có thể truy cập được hay không và không sử dụng tính tham chiếu.
jbindel

2
Thật vậy, nó không sử dụng tính tham chiếu. Nhưng SWT là trường hợp đặc biệt khi chúng ta cần gọi dispose (), mặc dù trước tiên không cần gọi bất kỳ ret () nào.
Alex

Tôi chỉ muốn nói đến trường hợp không phải SWT.
jbindel

Đây là một bài viết về Quản lý tài nguyên hệ điều hành eclipse.org/articles/swt-design-2/swt-design-2.html
Alex

2
Trong trường hợp đó, hãy chỉnh sửa câu trả lời của bạn để loại bỏ tuyên bố về không thể đối với GC vì nó gây hiểu nhầm.
Donal Fellows

1

Trước hết, bạn sẽ làm phiền những người đã học C hoặc C ++ trước Java. Tôi sẽ để nó như một bài tập để người đọc quyết định xem đó là dân chuyên nghiệp hay lừa đảo.

Mặc dù chắc chắn có những tình huống trong đó các đối tượng được thiết kế rất ngắn, nhưng hầu hết thời gian nếu một cái gì đó đủ phức tạp để tạo ra một đối tượng, thì nó đủ phức tạp để có lý do chính đáng để giữ một tài liệu tham khảo, vì vậy không nên giữ nó ít nhất là một cảnh báo để kiểm tra lại nếu bạn đã bỏ lỡ điều gì đó.

Ví dụ, trong một hướng dẫn, không ai quan tâm đến việc giữ một tham chiếu luồng, nhưng trong cuộc sống thực, nếu một cái gì đó đủ lâu để bạn muốn sinh ra một luồng, thường sẽ đủ lâu để bạn có thể hủy bỏ chuỗi. Hoặc nếu thời gian ngắn hơn, bạn thường sinh ra một loạt các chủ đề bạn sẽ muốn jointrước khi tiếp tục. Hoặc bạn muốn chắc chắn rằng việc tạo chủ đề của bạn thực sự thành công. Hoặc bạn muốn đảm bảo luồng hoàn thành sạch sẽ trước khi thoát. Bạn nhận được hình ảnh.


2
Là lo lắng về các lập trình viên gây phiền nhiễu từ các ngôn ngữ khác thực sự là mối quan tâm đầu tiên?
Nút840

Nó làm cho nó trở thành một vấn đề dễ đọc / quen thuộc / phong cách tùy thuộc vào thành phần của nhóm của bạn, bởi vì đó là một phong cách được nhiều người thực hiện. Ngay cả những người chưa bao giờ lập trình trong C ++ cũng thường áp dụng các phong cách từ những người cố vấn của họ.
Karl Bielefeldt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.