เหตุผลที่Optional
ถูกเพิ่มลงใน Java เป็นเพราะ:
return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.findFirst()
.getOrThrow(() -> new InternalError(...));
สะอาดกว่านี้:
Method matching =
Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.getFirst();
if (matching == null)
throw new InternalError("Enclosing method not found");
return matching;
จุดของฉันคือตัวเลือกที่ถูกเขียนขึ้นเพื่อสนับสนุนการเขียนโปรแกรมการทำงานซึ่งถูกเพิ่มไปยัง Java ในเวลาเดียวกัน (ตัวอย่างมาจากความอนุเคราะห์ของบล็อกโดย Brian Goetzตัวอย่างที่ดีกว่าอาจใช้orElse()
วิธีนี้เนื่องจากรหัสนี้จะทำให้เกิดข้อยกเว้นอยู่ดี แต่คุณจะได้ภาพ)
แต่ตอนนี้ผู้คนกำลังใช้ตัวเลือกด้วยเหตุผลที่แตกต่างกันมาก พวกเขากำลังใช้เพื่อแก้ไขข้อบกพร่องในการออกแบบภาษา ข้อบกพร่องคือ: ไม่มีวิธีระบุพารามิเตอร์ของ API และค่าส่งคืนที่อนุญาตให้เป็นโมฆะ อาจถูกกล่าวถึงใน javadocs แต่นักพัฒนาส่วนใหญ่ไม่ได้เขียน javadocs สำหรับรหัสของพวกเขาและมีไม่มากที่จะตรวจสอบ javadocs ขณะที่พวกเขาเขียน ดังนั้นสิ่งนี้นำไปสู่โค้ดจำนวนมากที่ตรวจสอบค่าว่างก่อนใช้งานแม้ว่าจะไม่สามารถเป็นโมฆะได้เพราะพวกเขาได้รับการตรวจสอบซ้ำแล้วซ้ำอีกเก้าหรือสิบเท่าของสแต็กการโทร
ฉันคิดว่ามีความกระหายที่แท้จริงในการแก้ไขข้อบกพร่องนี้เพราะผู้คนจำนวนมากที่เห็นคลาสตัวเลือกใหม่สันนิษฐานว่าจุดประสงค์ของมันคือการเพิ่มความชัดเจนให้กับ API ทำไมคนถามคำถามเช่น "ควร getters คืน Optionals?" ไม่พวกเขาอาจไม่ควรเว้นเสียแต่ว่าคุณคาดหวังให้ผู้ใช้ทะเยอทะยานมาใช้ในการเขียนโปรแกรมการทำงานซึ่งไม่น่าเป็นไปได้มากนัก ในความเป็นจริงถ้าคุณดูที่ใช้เป็นตัวเลือกใน Java API นั้นส่วนใหญ่จะอยู่ในชั้นเรียนสตรีมซึ่งเป็นแกนหลักของการเขียนโปรแกรมการทำงาน (ฉันไม่ได้ตรวจสอบอย่างละเอียดมาก แต่คลาส Stream อาจเป็นเพียงคลาสเดียวเท่านั้นที่ใช้)
หากคุณวางแผนที่จะใช้ getter ในบิตของรหัสการทำงานมันอาจเป็นความคิดที่ดีที่จะมี getter มาตรฐานและอีกอันหนึ่งที่ส่งกลับเป็นตัวเลือก
โอ้และถ้าคุณต้องการให้คลาสของคุณเป็นแบบอนุกรมคุณไม่ควรใช้ตัวเลือกอย่างแน่นอน
ตัวเลือกเป็นวิธีแก้ปัญหาข้อบกพร่อง API ที่ไม่ดีนักเนื่องจากก) พวกเขามีรายละเอียดมากและข) พวกเขาไม่เคยตั้งใจจะแก้ไขปัญหานั้นตั้งแต่แรก
ทางออกที่ดีกว่าสำหรับข้อบกพร่องของ API คือตัวตรวจสอบ Nullnessตรวจสอบ นี่เป็นตัวประมวลผลคำอธิบายประกอบที่ช่วยให้คุณระบุพารามิเตอร์และค่าส่งคืนที่ได้รับอนุญาตให้เป็นโมฆะโดยใส่คำอธิบายประกอบด้วย @Nullable ด้วยวิธีนี้คอมไพเลอร์สามารถสแกนรหัสและหาว่าค่าที่สามารถเป็นโมฆะจริงจะถูกส่งผ่านไปยังค่าที่ไม่อนุญาตให้เป็นโมฆะ โดยค่าเริ่มต้นจะถือว่าไม่มีสิ่งใดได้รับอนุญาตให้เป็นโมฆะยกเว้นว่ามีการเพิ่มความคิดเห็น ด้วยวิธีนี้คุณไม่ต้องกังวลกับค่าว่าง การส่งค่า Null ไปยังพารามิเตอร์จะส่งผลให้เกิดข้อผิดพลาดของคอมไพเลอร์ การทดสอบวัตถุสำหรับค่า null ที่ไม่สามารถเป็นค่า null จะสร้างคำเตือนคอมไพเลอร์ ผลกระทบของสิ่งนี้คือการเปลี่ยน NullPointerException จากข้อผิดพลาดรันไทม์เป็นข้อผิดพลาดเวลารวบรวม
สิ่งนี้เปลี่ยนแปลงทุกสิ่ง
สำหรับผู้ได้รับของคุณอย่าใช้ทางเลือก และพยายามออกแบบชั้นเรียนของคุณเพื่อไม่ให้สมาชิกคนใดเป็นโมฆะ และอาจลองเพิ่ม Nullness Checker ในโครงการของคุณและประกาศ getters และพารามิเตอร์ setter ของคุณ @Nullable หากต้องการ ฉันทำสิ่งนี้กับโครงการใหม่เท่านั้น มันอาจสร้างคำเตือนจำนวนมากในโครงการที่มีอยู่ซึ่งเขียนด้วยการทดสอบฟุ่มเฟือยมากมายสำหรับโมฆะดังนั้นจึงอาจเป็นเรื่องยากที่จะติดตั้งเพิ่มเติม แต่มันก็จะจับข้อบกพร่องมากมาย ฉันรักมัน. รหัสของฉันสะอาดกว่าและเชื่อถือได้มากกว่าเพราะมัน
(นอกจากนี้ยังมีภาษาใหม่ที่ระบุสิ่งนี้ Kotlin ซึ่งรวบรวมรหัส Java byte ช่วยให้คุณระบุว่าวัตถุอาจเป็นโมฆะเมื่อคุณประกาศมันเป็นวิธีที่สะอาดขึ้น)
ภาคผนวกในโพสต์ดั้งเดิม (รุ่น 2)
หลังจากให้ความคิดจำนวนมากฉันได้ข้อสรุปอย่างไม่เต็มใจที่จะยอมรับตัวเลือกคืนในเงื่อนไขเดียว: ค่าที่ดึงมาอาจเป็นจริง ฉันเห็นโค้ดจำนวนมากที่ผู้คนส่งคืนเป็นประจำตัวเลือกจากผู้ได้รับที่ไม่สามารถคืนค่าว่างได้ ฉันเห็นว่านี่เป็นวิธีการเขียนโค้ดที่แย่มากซึ่งเพิ่มความซับซ้อนให้กับโค้ดเท่านั้นซึ่งจะทำให้บั๊กมีโอกาสมากขึ้น แต่เมื่อค่าที่ส่งคืนอาจเป็นโมฆะจริงไปข้างหน้าและล้อมรอบภายในตัวเลือก
โปรดทราบว่าวิธีการที่ออกแบบมาสำหรับการเขียนโปรแกรมใช้งานได้และต้องมีการอ้างอิงฟังก์ชันจะ (และควร) เขียนในสองรูปแบบซึ่งหนึ่งในนั้นใช้ทางเลือก ตัวอย่างเช่นOptional.map()
และOptional.flatMap()
ทั้งคู่รับฟังก์ชั่นอ้างอิง คนแรกรับการอ้างอิงถึงผู้ทะเยอทะยานธรรมดาและคนที่สองรับหนึ่งที่ส่งกลับตัวเลือก ดังนั้นคุณไม่ได้ทำให้คนอื่นชอบโดยการส่งกลับทางเลือกที่ค่าไม่สามารถเป็นโมฆะ
ต้องบอกว่าทั้งหมดที่ฉันยังคงเห็นวิธีการที่ใช้โดยNullness Checkerเป็นวิธีที่ดีที่สุดในการจัดการกับ nulls เนื่องจากพวกเขาเปิด NullPointerExceptions จากข้อบกพร่อง runtime เพื่อรวบรวมข้อผิดพลาดเวลา