มันเป็นการปฏิบัติที่ไม่ถูกต้องหรือไม่ในการสร้างวัตถุใหม่โดยไม่เก็บไว้


23

ฉันเคยเห็นวัตถุที่สร้างขึ้นในรหัส Java โดยไม่ต้องจัดเก็บการอ้างอิงถึงวัตถุ ตัวอย่างเช่นในปลั๊กอิน eclipse ฉันเห็น SWT Shell ที่สร้างขึ้นเช่น:

new Shell();

วัตถุเชลล์ใหม่นี้ไม่ได้เก็บไว้ในตัวแปร แต่จะยังคงอ้างอิงจนกว่าจะมีการกำจัดหน้าต่างซึ่ง [ฉันเชื่อว่า?] จะเกิดขึ้นตามค่าเริ่มต้นเมื่อปิดหน้าต่าง

มันเป็นการปฏิบัติที่ไม่ถูกต้องหรือไม่ในการสร้างวัตถุเช่นนี้ หรือว่าห้องสมุดออกแบบมาไม่ดี? ถ้าฉันไม่ต้องการการอ้างอิง แต่ต้องการเพียง "ผลข้างเคียง" ของวัตถุ? ฉันควรจะเก็บข้อมูลอ้างอิงไว้หรือไม่?

UPDATE:

ชื่นชมตัวอย่างข้างต้นของฉันไม่ดี ในขณะที่ฉันได้เห็นองค์ประกอบ UI ที่สร้างขึ้นเช่นนี้การสร้าง SWT Shell แบบนี้อาจไม่มีจุดหมายเพราะคุณจำเป็นต้องเรียกใช้วิธีการเปิดบนอินสแตนซ์เชลล์ มีตัวอย่างที่ดีขึ้นโดย aixเช่นต่อไปนี้จากการสอนพร้อมกัน Java :

(new HelloThread()).start();

การฝึกฝนนี้มีให้เห็นในหลายบริบทดังนั้นคำถามยังคงอยู่ เป็นการปฏิบัติที่ดีหรือไม่?


2
จุดประสงค์ของการจัดเก็บข้อมูลอ้างอิงคืออะไร
Daniel R Hicks

(มันอาจจะดีกว่าจากมุมมองแนวคิดที่จะมีวิธีคงที่เช่นShell.createTopLevelShell()หรืออะไรก็ตามเทียบกับการใช้ตัวสร้างในกรณีนี้ แต่การทำงานมีความแตกต่างเล็กน้อย)
Daniel R Hicks

คำถามนี้เกี่ยวกับการฝึกฝนการสร้างวัตถุโดยไม่อ้างอิงถึงพวกมันสร้างคลาสที่ต้องใช้การฝึกฝนนี้หรือเป็นเรื่องเกี่ยวกับวิธีที่ SWT ใช้รูปแบบนี้เป็นพิเศษหรือไม่?
StriplingWarrior

1
วัตถุ SWT จะต้องเป็นdispose()d: กฎข้อที่ 1: ถ้าคุณสร้างขึ้นมาคุณจะกำจัดมัน eclipse.org/articles/swt-design-2/swt-design-2.html
jbindel

2
ฉันจะใช้ตัวแปรเพื่อเก็บการอ้างอิงสำหรับการแก้ไขจุดบกพร่อง หากคุณมีจุดพักในวิธีนี้คุณสามารถรับตัวดีบักเกอร์เพื่อสอบถามวัตถุผ่านตัวแปรโลคัล หากไม่มีการอ้างอิงฉันมั่นใจว่ามันเป็นไปได้ แต่อาจเป็นเรื่องยากมาก
Martin York

คำตอบ:


12

มีองค์ประกอบของความชอบส่วนตัว แต่ฉันคิดว่าการไม่เก็บข้อมูลอ้างอิงนั้นไม่จำเป็นต้องเป็นวิธีปฏิบัติที่ไม่ดี

ลองพิจารณาตัวอย่างสมมุติต่อไปนี้:

new SingleFileProcessor().process(file);

หากจำเป็นต้องสร้างวัตถุตัวประมวลผลใหม่สำหรับทุกไฟล์และไม่จำเป็นหลังจากการprocess()โทรไม่มีจุดในการจัดเก็บข้อมูลอ้างอิง

นี่เป็นอีกตัวอย่างหนึ่งที่นำมาจากการสอนพร้อมกันของ Java :

(new HelloThread()).start();

ฉันเคยเห็นตัวอย่างอื่น ๆ มากมายเมื่อไม่ได้จัดเก็บข้อมูลอ้างอิงและนั่นอ่านได้ดีกับตาของฉันเช่น:

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

( StringBuilderไม่ได้เก็บวัตถุ)

มีรูปแบบที่คล้ายกันซึ่งเกี่ยวข้องกับ common.lang's HashCodeBuilderet al.


2
@ BalusC: ด้วยความเคารพฉันไม่เห็นสิ่งที่ทำให้มันคาวและวิธีการมีวิธีการที่โรงงานดีกว่า (ฉันสมมติว่าตัวอย่างของคุณคล้ายกับของฉันและgetInstance()เป็นโรงงานและไม่ใช่ซิงเกิล)
NPE

มันขึ้นอยู่กับโรงงานว่าจะใช้ซิงเกิลตันหรือไม่ ผู้โทรเข้าโรงงานไม่ควรคิดมากนัก
Donal Fellows

ในตัวอย่างของคุณอินสแตนซ์ FileProcessor นั้น (ไม่น่าจะเป็นไปได้) เมื่อคำสั่งเสร็จสมบูรณ์ในขณะที่ในตัวอย่างของ OP กรณีของอินสแตนซ์เชลล์คือ (ภายใต้หน้าปก) ที่อ้างอิงโดยวัตถุอื่นและการอ้างอิงนั้น ระยะเวลาของคำสั่ง
Daniel R Hicks

@BalusC: FileProcessor processอาจมีวิธีการอื่นที่จะปรับเปลี่ยนลักษณะการทำงานของ
วินไคลน์

7

หากคุณไม่ต้องการการอ้างอิงไปยังวัตถุที่สร้างขึ้นแล้วอย่ายึดการอ้างอิง มันง่ายอย่างที่คิด


5

โดยทั่วไปเป็นแนวปฏิบัติที่ดีที่จะเผยแพร่การอ้างอิงโดยเร็วที่สุดเท่าที่จะทำได้ ฉันไม่เห็นความแตกต่างระหว่าง:

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

และ

(new HelloThread()).start();

เท่าที่เกี่ยวข้องกับรหัสคุณเพียงแค่หลีกเลี่ยงการใช้ชื่อตัวแปรซึ่งอาจเป็นสิ่งที่ดี คอมไพเลอร์ JIT โดยทั่วไปฉลาดพอที่จะรับรู้ว่ามันสามารถเก็บรวบรวมเธรดได้หลังจากการใช้งานครั้งล่าสุดดังนั้นอาจไม่มีความแตกต่างจากมุมมองประสิทธิภาพ

ปัญหาที่แท้จริงเพียงอย่างเดียวที่ต้องหลีกเลี่ยงคือรหัสใน Constructor Anti-Patternแต่มันไม่ได้ฟังดูเหมือนเป็นสิ่งที่คุณถาม


3

สิ่งนี้อาจไม่ดีหากคุณใช้ SWT เนื่องจากคุณต้องล้างข้อมูลด้วยตัวคุณเอง (เรียกใช้วิธีการกำจัด () แต่สำหรับชั้นเรียนอื่น ๆ (ไม่ใช่ SWT) ก็โอเค

นี่คือบทความเกี่ยวกับการจัดการทรัพยากรระบบปฏิบัติการ


การอ้างอิงแบบวงกลมไม่ได้ป้องกันวัตถุจากการรวบรวมขยะใน Java Java VM ที่ทันสมัยใด ๆ จะกำหนดว่าวัตถุนั้นเป็น GCable หรือไม่ขึ้นอยู่กับว่าสามารถเข้าถึงได้หรือไม่และไม่ใช้การนับการอ้างอิง
jbindel

2
แน่นอนมันไม่ได้ใช้การนับการอ้างอิง แต่ SWT เป็นกรณีพิเศษที่เราจำเป็นต้องเรียกการกำจัด () แม้ว่าจะไม่จำเป็นต้องเรียกการเก็บรักษาใด ๆ () ก่อน
Alex

ฉันหมายถึงการอ้างถึงกรณีที่ไม่ใช่ SWT
jbindel

นี่คือบทความเกี่ยวกับการจัดการทรัพยากรระบบปฏิบัติการeclipse.org/articles/swt-design-2/swt-design-2.html
Alex

2
ในกรณีนั้นให้แก้ไขคำตอบของคุณเพื่อลบข้อความที่เกี่ยวกับ
Donal Fellows

1

ก่อนอื่นคุณจะไปรบกวนคนที่เรียนรู้ C หรือ C ++ ต่อหน้า Java ฉันจะปล่อยให้มันเป็นแบบฝึกหัดสำหรับผู้อ่านที่จะตัดสินใจว่าเป็นมืออาชีพหรือแย้ง

ในขณะที่มีสถานการณ์ที่วัตถุถูกออกแบบมาให้สั้นมาก แต่ส่วนใหญ่หากมีสิ่งที่ซับซ้อนพอที่จะสร้างวัตถุสำหรับมันมันซับซ้อนพอที่จะมีเหตุผลที่ดีในการอ้างอิงดังนั้นจึงไม่ควรทำ อย่างน้อยที่สุดก็เป็นคำเตือนให้ตรวจสอบอีกครั้งหากคุณพลาดบางสิ่งบางอย่าง

ตัวอย่างเช่นในบทช่วยสอนไม่มีใครสนใจเกี่ยวกับการเก็บการอ้างอิงเธรด แต่ในชีวิตจริงหากสิ่งใดใช้เวลานานพอที่คุณต้องการวางไข่เธรดโดยทั่วไปจะใช้เวลานานพอที่คุณต้องการยกเลิกเธรด หรือถ้าอายุสั้นกว่าปกติคุณจะวางไข่เป็นกลุ่มของเธรดที่คุณต้องการjoinก่อนดำเนินการต่อ หรือคุณต้องการให้แน่ใจว่าการสร้างเธรดของคุณสำเร็จแล้ว หรือคุณต้องการให้แน่ใจว่าด้ายเสร็จเรียบร้อยก่อนที่จะออก คุณได้รับรูปภาพ


2
กังวลเกี่ยวกับโปรแกรมเมอร์ที่น่ารำคาญจากภาษาอื่น ๆ จริง ๆ ความกังวลแรกหรือไม่
Buttons840

มันทำให้อ่านง่าย / คุ้นเคย / ปัญหาสไตล์ขึ้นอยู่กับองค์ประกอบของทีมของคุณเพราะมันเป็นสไตล์ที่ผู้คนจำนวนมากดำเนินการ แม้แต่คนที่ไม่เคยตั้งโปรแกรมใน C ++ ก็มักจะนำเอาสไตล์จากที่ปรึกษาของพวกเขาที่ทำ
Karl Bielefeldt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.