ทำไม Java มีวิธีการ 'โมฆะ'?


52

Java / ทำไมต้องมีvoidวิธีการ? เอกสารอ้างอิง :

วิธีการใด ๆ ที่ประกาศเป็นโมฆะจะไม่ส่งคืนค่า

เท่าที่ผมสามารถคิดว่าการใช้งานของทุกคนจะได้รับการบริการที่ดีขึ้นโดยการกลับธงสถานะวัตถุที่ถูกเรียกหรือvoidnull

สิ่งนี้จะทำให้การเรียกใช้คำสั่งที่กำหนดได้และจะช่วยให้รูปแบบการสร้างและวิธีการผูกมัด วิธีการที่ถูกเรียกใช้เฉพาะกับเอฟเฟกต์ของพวกเขามักจะส่งคืนบูลีนหรือSuccessประเภททั่วไปหรือส่งข้อยกเว้นเมื่อล้มเหลว


เพื่อที่เราจะได้ไม่ต้องใช้ไวยากรณ์พิเศษในการเขียนรูทีนย่อย เราสามารถใช้ฟังก์ชั่นเดียวกับที่ใช้
candied_orange

คำตอบ:


159

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


10
แต่ไม่ว่าจะสำเร็จหรือล้มเหลวเป็นสิ่งที่แสดงออกโดยการขว้างหรือไม่โยนข้อยกเว้นไม่ใช่คืนค่าสถานะ และการกลับมาvoidไม่ได้พูดอะไรเกี่ยวกับว่าวิธีการหรือฟังก์ชั่นนั้นรู้ตัวเองเพียงพอที่จะโยนตามความเหมาะสม
Volker Siegel

12
@VolkerSiegel: บริบทของคำตอบคือคำถาม OP แนะนำว่าในทุกกรณีที่มีการใช้โมฆะฟังก์ชันควรส่งคืนค่าสถานะสถานะซึ่งบ่งชี้ความสำเร็จของความล้มเหลว ในบริบทนั้นการคืนค่าเป็นโมฆะแท้จริงแล้วบอกว่าฟังก์ชั่นที่แท้จริงไม่มีอะไรจะกลับมา การบังคับให้ฟังก์ชันส่งคืน 0 เสมอเพื่อระบุว่าสำเร็จจะทำให้ผู้ใช้มั่นใจได้ว่าฟังก์ชันนั้นตรวจสอบข้อผิดพลาดเมื่อในความเป็นจริงค่าส่งคืนจะเป็น 0 เสมอโดยไม่คำนึงถึงความสำเร็จหรือความล้มเหลว
slebetman

19
@VolkerSiegel มีสถานการณ์จำนวนมากที่ข้อยกเว้นไม่ใช่วิธีที่ถูกต้องในการทำสิ่งต่าง ๆ ในความเป็นจริงฉันพูดได้ยากกว่าสำหรับการยกเว้นว่าถูกกว่าผิด - ข้อยกเว้นหมายถึงสิ่งที่น่ากลัวเกิดขึ้นที่ต้องมีการพิจารณา กรณีความล้มเหลวที่คาดไว้ไม่ควรใช้ข้อยกเว้น
Gabe Sechan

35
@GabeSechan ไม่ข้อยกเว้นควรถูกส่งออกหากวิธีการไม่สามารถทำตามสัญญาได้ หากวิธีการนั้นต้องการการอ้างอิงแบบไม่เป็นโมฆะ แต่มันได้รับอย่างใดอย่างหนึ่งนั่นคือความล้มเหลวที่คาดหวังและมันควรจะโยน
Andy

5
มีไวยากรณ์ทางเลือกมากมายที่จะแก้ไข เหตุผลที่พวกเขาเลือกโซลูชันนี้ (น่าอึดอัดใจ) ก็เพราะว่า C ใช้งาน
Marco van de Voort

96
  1. เนื่องจาก C มีvoidชนิดและ Java ได้รับการออกแบบให้ปฏิบัติตามอนุสัญญาของตระกูลภาษา C
  2. มีฟังก์ชั่นมากมายที่คุณไม่ต้องการคืนค่า คุณจะทำอย่างไรกับ " Successประเภททั่วไป" ต่อไป? ในความเป็นจริงค่าส่งคืนเพื่อบ่งชี้ความสำเร็จมีความสำคัญน้อยกว่าใน Java มากกว่าใน C เนื่องจาก Java มีข้อยกเว้นในการบ่งชี้ความล้มเหลวและ C ไม่ได้

8
> "คุณจะทำอย่างไรกับ" ประเภทความสำเร็จทั่วไป "ต่อไป?" - เมื่อเขียนโค้ดทั่วไปประเภทของค่าเดียว (เรียกว่า Unit type btw) มีประโยชน์มากเพราะมันจะกำจัดฟังก์ชันพิเศษของฟังก์ชันที่ "เพิ่งกลับมา" แต่ไม่ได้คืนสิ่งใดเป็นพิเศษ แต่เมื่อ Java ถูกสร้างขึ้นครั้งแรกมันมีระบบการพิมพ์ที่แสดงออกน้อยกว่า (ไม่มีพารามิเตอร์ประเภท) ดังนั้นจึงมีความแตกต่างในทางปฏิบัติไม่มาก และตอนนี้มันก็สายเกินไปที่จะเปลี่ยนแปลง ภาษาที่ทันสมัยมากขึ้นจริงหลบเลี่ยงโมฆะ "พิมพ์" (อันที่จริงมันไม่ได้เป็นเพียงแค่ประเภทเครื่องหมายพิเศษสำหรับวิธีการ) และใช้หน่วยประเภทแทน
Sarge Borsch

9
@SargeBorsch Voidประเภทของ Java ทำหน้าที่เป็นหน่วยประเภท (เช่นสำหรับ Generics) แต่น่าเสียดายที่มันแตกต่างจากvoid(หมายเหตุด้านข้าง: ลูกแมวน่ากอดตายทุกครั้งที่คุณคิดค้นรูปแบบใหม่เพื่อแก้ไขประเภทที่คุณสับสนในรุ่นก่อนหน้า) หากใครไม่คุ้นเคยกับประเภทของหน่วยนี่เป็นคำนำที่ดี: en.wikipedia.org/wiki/Unit_type
Ogre Psalm33

1
@ OgrePsalm33 มันไม่ได้ทำหน้าที่เป็นหน่วยประเภท (อย่างน้อยในทางปฏิบัติ - หนึ่งยังคงต้องเขียน "คืนโมฆะ" เพื่อกลับจากวิธีการที่มีประเภทคืนโมฆะและคอมไพเลอร์ AFAIK จะจัดสรรพื้นที่บนสแต็คสำหรับการอ้างอิงเป็นโมฆะ ไม่ใช่การใช้ประโยชน์จากความจริงที่ว่าไม่มีประโยชน์ที่จะอ่านค่าเหล่านี้) มันเป็นเพียงข้อตกลงที่จะใช้ในกรณีที่ประเภทของหน่วย "เหมาะสม" จะเหมาะสมกว่า
Sarge Borsch

3
@immibis เนื่องจากหน่วยประเภทตามคำจำกัดความต้องมีค่าเดียวค่าหนึ่งและ Void ไม่มีค่า ใช่มันเป็นไปได้ที่จะใช้null(อันที่จริงนี่เป็นตัวเลือกเดียว) แต่ null เป็นสิ่งพิเศษค่าประเภทการอ้างอิงใด ๆ ใน Java อาจเป็นโมฆะ (นี่เป็นความผิดพลาดอีกประการหนึ่งในการออกแบบภาษา) และอย่างที่ฉันได้กล่าวไปแล้วถ้าคุณใช้Voidreturn type แทนvoidmark คอมไพเลอร์ Java ไม่ใช่เพื่อนของคุณ
Sarge Borsch

5
เป็นโมฆะ @SargeBorsch nullมีตรงหนึ่งค่าซึ่งเป็น ความจริงที่ว่าnullเป็นสมาชิกประเภทส่วนใหญ่ไม่เกี่ยวข้องกับว่าVoidเป็นหน่วยประเภท
user253751

65

เดิมเหตุผลว่าทำไมภาษาที่มีvoidชนิดเป็นเพราะเหมือนในCกรรมวิธีของภาษาไม่ต้องการที่จะไม่จำเป็นซับซ้อนไวยากรณ์ของภาษาที่มีขั้นตอนและฟังก์ชั่นของทางปาสคาลได้

นั่นคือเหตุผลดั้งเดิม

คำแนะนำของคุณ:

คืนสถานะธง

นั่นเป็นข้อห้าม เราไม่ใช้สถานะธง หากมีข้อผิดพลาดเราจะรายงานผ่านข้อยกเว้น

วัตถุที่ถูกเรียก

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

คืนค่า null

มันจะบังคับให้คุณประกาศวิธีที่จะคืนบางสิ่งบางอย่างในความเป็นจริงมันไม่ได้ส่งคืนอะไรเลยดังนั้นมันจะสร้างความสับสนให้กับคนที่กำลังมองหาอินเทอร์เฟซที่พยายามจะเข้าใจว่ามันทำอะไร ผู้คนจะสร้างคลาสที่ไร้ประโยชน์อย่างหลีกเลี่ยงไม่ได้ซึ่งหมายถึง "no return value" อย่างหลีกเลี่ยงไม่ได้ดังนั้นฟังก์ชั่นทั้งหมดที่ไม่มีสิ่งใดที่จะส่งกลับสามารถส่งคืนการอ้างอิงที่เป็นโมฆะของคลาสนั้นได้ นั่นจะเป็น clunky voidโชคดีมีวิธีแก้ปัญหานี้จะเรียกว่า และนั่นคือคำตอบสำหรับคำถามของคุณ


3
โปรดระบุแหล่งที่มาสำหรับ "สาเหตุดั้งเดิม ... " สำหรับความรู้ของฉันเหตุผลที่แท้จริงคือ C ถูกออกแบบมาให้เป็นแอสเซมเบลอร์แบบพกพา
Thorbjørn Ravn Andersen

6
@ ThorbjørnRavnAndersenคุณจริง ๆ ขอให้ฉันให้แหล่งที่มาสำหรับการเรียกร้องว่าไวยากรณ์ของจาวามาจากไวยากรณ์ C?
Mike Nakis

3
@ ThorbjørnRavnAndersenโอ้ฉันเข้าใจแล้วฉันเข้าใจผิด ดังนั้นคุณต้องการแหล่งที่มาสำหรับการเรียกร้องของฉันเกี่ยวกับ C ไม่ใช่เกี่ยวกับ Java โอเคฉันขอโทษฉันไม่มีที่มาสำหรับเรื่องนั้น แต่ฉันคิดว่ามันค่อนข้างชัดเจน (ฉันเคยเขียนโปรแกรมในปาสคาลในปี 1987 เมื่อฉันเปลี่ยนมาเป็นค. ความดีของฉันนั่นคือ 30 ปีที่แล้ว)
Mike Nakis

6
มันไม่ชัดเจน C ได้รับการพัฒนาอย่างคร่าว ๆ ในเวลาเดียวกับคนปาสกาลที่มีแนวโน้มว่าจะไม่รู้ด้วยซ้ำ โปรดอย่าระบุสมมติฐานเป็นข้อเท็จจริง
Thorbjørn Ravn Andersen

12
จริงเหตุผลเดิมคือว่าโดยฟังก์ชั่นเริ่มต้น C กลับintเพื่อให้คำหลักที่ถูกเพิ่มเข้ามาภายหลังจาก K & R เพื่อบ่งบอก 'ไม่พิมพ์กลับ'
user207421

20

วิธีการบางอย่างเช่นSystem.out.printlnไม่ได้ส่งคืนสิ่งที่มีประโยชน์ แต่จะเรียกว่าหมดจดสำหรับผลข้างเคียงนี้ voidเป็นตัวบ่งชี้ที่เป็นประโยชน์สำหรับคอมไพเลอร์และสำหรับผู้อ่านของรหัสที่ไม่มีค่าที่เป็นประโยชน์จะถูกส่งกลับ

กลับมาnullแทนvoidหมายความว่าคุณจะได้รับNullPointerExceptionช่วงเวลาที่คุณใช้ค่านี้เพื่ออะไร ดังนั้นคุณแลกเปลี่ยนข้อผิดพลาดเวลารวบรวมสำหรับข้อผิดพลาดรันไทม์ซึ่งเป็นวิธีที่เลวร้ายยิ่ง นอกจากนี้คุณจะต้องกำหนดประเภทผลตอบแทนเป็นObjectซึ่งจะทำให้เข้าใจผิดและสับสน (และการผูกมัดจะยังคงไม่ทำงาน)

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

การส่งคืนthisไม่สามารถทำได้จากวิธีการคงที่

การส่งคืนSuccessวัตถุทั่วไปจะไม่มีวัตถุประสงค์ที่มีประโยชน์


1
เห็นด้วยทั้งหมดกับคุณคำตอบที่ง่ายที่สุดและรัดกุมที่สุด
webo80

11

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

สิ่งที่ควรArrays.sort(a)กลับมา?

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

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

และถ้าคุณกลับอย่างอื่นที่ไร้สาระโดยสิ้นเชิง (เช่นความยาวของa) แล้วมันก็ทำให้การใช้ค่าตอบแทนที่ทำให้เกิดความสับสนจริงๆ - เพียงแค่คิดว่าวิธีการที่ทำให้เกิดความสับสนมากขึ้นก็คือการพูดint len = Arrays.sort(a)แทนint len = A.length!


1
ในความเป็นธรรมทั้งหมดโปรแกรมเมอร์ไม่จำเป็นต้องเขียนreturn null;- JVM ก็สามารถออกคำสั่งได้เช่นกันว่าหากการควบคุมหลุดออกจากจุดสิ้นสุดของฟังก์ชั่นโดยวิธีอื่นนอกเหนือจากที่ชัดเจนreturnหรือthrowคำสั่งnullจะถูกส่งกลับไปยังผู้โทรโดยปริยาย IIRC C ทำเช่นนั้นยกเว้นว่าค่าส่งคืนจะไม่ได้กำหนดไว้ในกรณีนั้น (จะเป็นค่าใดก็ตามที่เกิดขึ้นในตำแหน่งที่ใช้สำหรับค่าส่งคืนในเวลานั้น)
CVn

2
คำตอบที่ถูกต้องสำหรับคำถามที่เป็นตัวหนาของคุณคือ "อาร์เรย์ที่เรียงลำดับ"
ไบรอัน Boettcher

2
@BryanBoettcher: คุณไม่ได้อ่านส่วนที่เหลือเหรอ?
Mehrdad

1
@Michael Kjörling: มันเป็นคุณสมบัติพื้นฐานของภาษาจาวาเพื่อป้องกันข้อผิดพลาดดังกล่าวคือไม่มีพฤติกรรมที่ไม่ได้กำหนดหากคุณลืมreturnคำสั่ง แต่คุณจะได้รับข้อผิดพลาดของคอมไพเลอร์ที่บอกคุณถึงความผิดพลาดของคุณ การแทรกนัยreturn null;จะดีกว่า“ พฤติกรรมที่ไม่ได้กำหนด” แต่ไม่มาก มันจะมีประโยชน์ก็ต่อเมื่อชนิดคืนกลับไม่มีความหมาย แต่คอมไพเลอร์ดึงข้อสรุปมาจากที่ใดว่าค่าส่งคืนไม่มีความหมายเมื่อไม่มีvoid?
Holger

2
@ MichaelKjörling:“ ถ้าความreturnจริงไม่ได้เพิ่มคุณค่าใด ๆ ... ” ก็อย่างที่บอกกันว่าไม่มีตัวบ่งชี้สำหรับคอมไพเลอร์ว่าการคืนค่าจะไม่เพิ่มมูลค่าใด ๆ หากไม่มีvoidประเภท จริงๆแล้วมันตรงข้ามกับข้อสันนิษฐานแรกคือวิธีการประกาศประเภทส่งคืนต้องการreturnสิ่งที่มีประโยชน์ของประเภทนั้น และเรายังไม่ได้พูดเกี่ยวกับประเภทดั้งเดิมซึ่งยังไม่มีnullค่าดังนั้นค่าเริ่มต้นใด ๆ ที่คอมไพเลอร์จะฉีดจะขัดแย้งกับช่วงของค่าส่งคืนที่อาจเป็นประโยชน์
Holger

7

การคืนค่า a booleanซึ่งเท่ากับtrueที่คุณแนะนำเสมอไม่เพียง แต่ไร้จุดหมายเท่านั้น (ค่าส่งคืนจะไม่มีข้อมูล) แต่จะทำให้เข้าใจผิด ส่วนใหญ่เวลาที่ดีที่สุดที่จะใช้ชนิดผลตอบแทนเท่านั้นที่มีข้อมูลมากที่สุดเท่าที่สามารถใช้ได้จริง - ที่ว่าทำไมใน Java คุณมีbooleanสำหรับtrue/ falseแทนที่จะส่งคืนintกับ 4 พันล้านค่าที่เป็นไป ในทำนองเดียวกันการส่งคืนbooleanค่าที่เป็นไปได้สองค่าซึ่งมีค่าที่เป็นไปได้เพียงค่าเดียวเท่านั้น ("ความสำเร็จทั่วไป") จะทำให้เข้าใจผิด

มันจะเพิ่มค่าใช้จ่ายประสิทธิภาพที่ไม่จำเป็น

หากวิธีการนี้ใช้สำหรับผลข้างเคียงเท่านั้นจะไม่มีสิ่งใดที่จะส่งคืนและประเภทการคืนจะvoidสะท้อนกลับอย่างแน่นอน ข้อผิดพลาดที่อาจเกิดขึ้นน้อยสามารถส่งสัญญาณผ่านข้อยกเว้น

สิ่งหนึ่งที่อาจจะดีขึ้นจะทำให้ประเภทที่เกิดขึ้นจริงเช่นสกาล่าของvoid Unitสิ่งนี้จะช่วยแก้ปัญหาบางอย่างเช่นการจัดการยาสามัญ


สนุกจริง: List.addไม่เสมอกลับมาtrueแต่ที่สำหรับการเข้ากันได้กับสัญญาที่กว้างขึ้นCollection.addดังนั้นSet.addอาจจะกลับมาหรือtrue false
Holger

4

Java เป็นภาษาที่ค่อนข้างเก่า และในปี 1995 (เมื่อมันถูกสร้างขึ้น) และหลังจากนั้นไม่นานโปรแกรมเมอร์ก็กังวลอย่างมากเกี่ยวกับระยะเวลาที่กระบวนการเข้าควบคุมโปรเซสเซอร์รวมถึงการใช้หน่วยความจำ การคืนค่าเป็นโมฆะจะกำจัดวงจรนาฬิกาสองสามรอบและการใช้หน่วยความจำเล็กน้อยจากการเรียกใช้ฟังก์ชันเนื่องจากคุณไม่จำเป็นต้องใส่ค่าส่งคืนบนสแต็กและคุณจะไม่ต้องลบมันในภายหลัง

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


14
โปรแกรมเมอร์ที่มีความกังวลเกี่ยวกับความเร็วจะไม่ใช้ Java ในวันนี้เนื่องจากการใช้งานครั้งแรกของ Java ช้าฉาวโฉ่ ช้ามากจนหลายคนที่ไม่ได้ทำงานกับมันยังอยู่ภายใต้ความประทับใจที่ว่า Java เป็นคำพ้องสำหรับไขมันและช้า
Sarge Borsch

8
@SargeBorsch ทำให้ฉันนึกถึงเรื่องตลกการเขียนโปรแกรมเก่าจาก 20 ปีที่ผ่านมา "ก๊อกก๊อก." "ใครอยู่ตรงนั้นน่ะ?" ... ... ... ... ... หยุดนานมาก ... ... ... "Java"
Dan Neely

4
@DanNeely และบางครั้งหลังจากนั้นรถที่ใช้ระบบ AI ชนเข้ากับกำแพงด้วยความเร็วเต็มพิกัดไม่แม้แต่จะพยายามใช้เบรก มันเขียนใน Java ดังนั้น Java ไม่เบรกเลย! (มันเป็นภาษาปุนในภาษารัสเซียไม่สามารถแปลเป็นภาษาอังกฤษได้เป็นอย่างดี)
Sarge Borsch

2
@SargeBorsch สิ่งที่คุณได้ทำงานเป็นปุนภาษาอังกฤษแม้ว่ามันจะสูญเสียความแตกต่างนิดหน่อยในการแปล และการแปลการแปลน่าจะยากกว่าบทกวี
Dan Neely

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

2

ฉันได้อ่านข้อโต้แย้งที่ชี้ให้เห็นว่าตัวเลือกที่สอง (กลับthis) voidควรจะมีวิธีการแทน นี่เป็นความคิดที่ดี แต่วิธีการสร้างแบบไม่เป็นที่นิยมในขณะที่ Java ถูกสร้างขึ้น หากเป็นที่นิยมในขณะนั้นเหมือนตอนนี้นั่นอาจเป็นแนวทาง การกลับมาnullเป็นความคิดที่แย่จริงๆ ฉันหวังว่าจะnullไม่ได้เป็นภาษาเลยแม้แต่น้อย

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


2
@ จุดดีจุดนี้ไม่ใช้กับวิธีการคงที่
JimmyJames

14
@ marisbest2 ข้อโต้แย้งใด?
8bittree

3
ถ้าnullไม่ได้เป็นส่วนหนึ่งของภาษาผู้คนจะใช้ค่า Sentinel ทุกประเภทซึ่งหมายถึง "โปรดเพิกเฉยต่ออาร์กิวเมนต์ / ค่าส่งคืนนี้ไม่มีค่าที่สมเหตุสมผล" ปัญหาที่เกิดขึ้นnullไม่ใช่สิ่งที่ตัวเองเท่านั้นที่มีแนวโน้มที่จะใช้อย่างไม่ถูกต้อง ฉันอยากจะรู้ว่าปัญหานี้จะเกินจริงถ้ามาตรฐานnullจะถูกแทนที่ด้วยโซลูชั่นที่กำหนดเองจำนวนมากซึ่งการใช้งานแต่ละครั้งจะมีพฤติกรรมแตกต่างกันเช่นการเพิกเฉยต่อการใช้งานอย่างเงียบ ๆ หรือโยนข้อยกเว้นพิเศษแทนข้อยกเว้นตัวชี้มาตรฐาน null เป็นต้น
cmaster

2
@cmaster การแทนที่ที่ชัดเจนสำหรับnullประเภทตัวเลือกที่เหมาะสม (เช่นMaybeใน Haskell) ปัญหาเกี่ยวกับค่า null ใน Java คือไม่มีวิธีที่จะตัดสินใจได้ทันทีว่าค่านั้นเป็นโมฆะในทางปฏิบัติหรือไม่ สิ่งนี้นำไปสู่การเขียนโปรแกรมการป้องกันทั้งสองอย่างโดยไม่จำเป็น (ตรวจสอบค่า null โดยที่ไม่มีจุดหมายซึ่งจะเป็นการเพิ่มเปอร์เซ็นต์ของคนเซ่อในรหัส) และการผลิต NPE โดยไม่ตั้งใจ (หากลืมตรวจสอบว่าจำเป็น) ใช่มันถูกแก้ไขบางส่วนโดยคำอธิบายประกอบ แต่เป็นทางเลือกไม่ได้ตรวจสอบเสมอ ฯลฯ ดังนั้นพวกเขาจะไม่ช่วยคุณในขอบเขตด้วยรหัสบุคคลที่สาม
Sarge Borsch

2
@SargeBorsch ฉันเห็นด้วยกับ :-) การคัดค้านของฉันขัดกับภาษาที่ไม่มีวิธีมาตรฐานในการแสดง "โปรดเพิกเฉยต่อค่านี้" nullทำงานได้ดีสำหรับเรื่องนี้ (fine = simple) แต่ค่าตัวเลือกมาตรฐานที่มีความหมายที่มั่นคงเป็นอีกตัวเลือกที่ดี (fine = safe)
cmaster

2

อีกแง่มุม:

Java เป็นภาษาคงที่ที่มีคุณสมบัติค่อนข้างเข้มงวด ซึ่งหมายความว่ามีหลายสิ่งที่ค่อนข้างเปิดกว้างหรือมีพลวัตในภาษาอื่น (c / f Ruby, Lisp เป็นต้น) ได้รับการพิจารณาอย่างเคร่งครัด

นี่คือการตัดสินใจออกแบบทั่วไป "ทำไม" ยากที่จะตอบ (ดีเพราะนักออกแบบของภาษาคิดว่ามันจะดี!) "มีอะไรสำหรับ" สวยใส: จะช่วยให้คอมไพเลอร์ตรวจสอบจำนวนมากของข้อผิดพลาดซึ่งโดยทั่วไปเป็นคุณลักษณะที่ดีงามสำหรับภาษาใด ๆ ประการที่สองมันทำให้เปรียบเทียบได้ง่ายกับเหตุผลเกี่ยวกับภาษา ตัวอย่างเช่นมันค่อนข้างง่ายที่จะสร้างความถูกต้องอย่างเป็นทางการพิสูจน์ใน (ส่วนย่อยของ) ภาษา Java; เป็นการเปรียบเทียบซึ่งจะเป็นไปไม่ได้จริงในภาษาไดนามิกเช่น Ruby et al

ความคิดนี้แทรกซึมในภาษาตัวอย่างเช่นการประกาศบังคับใช้ข้อยกเว้นที่เป็นไปได้ที่วิธีการหนึ่งอาจใช้วิธีการแยกประเภทของinterfacevs. เทียบกับclassเพื่อหลีกเลี่ยงการถ่ายทอดทางพันธุกรรมที่คลุมเครือและอื่น ๆ สำหรับสิ่งที่มันเป็น (ภาษา OOP โลกแห่งความจำเป็นคงที่ที่มีความสำคัญและมุ่งเน้นไปที่การจัดการข้อผิดพลาดในการคอมไพล์เวลา) สิ่งเหล่านั้นจริง ๆ แล้วค่อนข้างหรูหราและทรงพลัง พวกเขาเข้ามาใกล้กับภาษาเชิงวิทยาศาสตร์ (Science'y) ซึ่งทำขึ้นโดยมีจุดประสงค์เพื่อสำรวจปัญหาเหล่านี้มากกว่าภาษาอื่น ๆ ในโลกแห่งความจริงก่อนหน้านี้ (ในเวลานั้นคุณต้องคำนึงถึง)

ดังนั้น. มีvoidประเภทที่เข้มงวดเป็นข้อความที่ชัดเจน: วิธีนี้จะไม่ส่งกลับสิ่งใดระยะเวลา มันเป็นสิ่งที่มันเป็น. การแทนที่โดยการบังคับให้ส่งคืนสิ่งที่มักจะนำไปสู่พฤติกรรมแบบไดนามิกมากขึ้น (เช่นใน Ruby ที่def ทุกคนมีค่าตอบแทนที่ชัดเจนหรือโดยปริยายเสมอ) ซึ่งจะไม่ดีสำหรับการพิสูจน์และเหตุผล; หรือการขยายขนาดใหญ่โดยใช้กลไกอื่น ๆ ที่นี่

(และ NB, ทับทิม (ตัวอย่าง) จัดการนี้แตกต่างกันและวิธีการแก้ปัญหาของมันยังคงตรงตามที่ได้รับการยอมรับว่าเป็นของ Java เพราะมีปรัชญาที่แตกต่างอย่างสิ้นเชิง. ตัวอย่างเช่นมันจะพ่น provability และสมเหตุสมผลสมบูรณ์ออกจากหน้าต่างในขณะที่การวางขนาดใหญ่มุ่งเน้นไปที่ ความสามารถในการใช้ภาษาสูงมาก)

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