ทำไมต้องโยน NullPointerException อย่างชัดเจนแทนที่จะปล่อยให้มันเกิดขึ้นเองตามธรรมชาติ?


182

เมื่ออ่านซอร์สโค้ดของ JDK ฉันพบว่าเป็นเรื่องธรรมดาที่ผู้เขียนจะตรวจสอบพารามิเตอร์ว่าเป็นโมฆะหรือไม่จากนั้นให้โยน NullPointerException () ใหม่ด้วยตนเอง ทำไมพวกเขาทำมัน ฉันคิดว่าไม่จำเป็นต้องทำเช่นนั้นเพราะมันจะโยน NullPointerException ใหม่ () เมื่อเรียกวิธีการใด ๆ (นี่คือซอร์สโค้ดของ HashMap ตัวอย่างเช่น :)

public V computeIfPresent(K key,
                          BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
    if (remappingFunction == null)
        throw new NullPointerException();
    Node<K,V> e; V oldValue;
    int hash = hash(key);
    if ((e = getNode(hash, key)) != null &&
        (oldValue = e.value) != null) {
        V v = remappingFunction.apply(key, oldValue);
        if (v != null) {
            e.value = v;
            afterNodeAccess(e);
            return v;
        }
        else
            removeNode(hash, key, null, false, true);
    }
    return null;
}

32
จุดสำคัญของการเข้ารหัสคือเจตนา
Scary Wombat

19
นี่เป็นคำถามที่ดีมากสำหรับคำถามแรกของคุณ! ฉันได้ทำการแก้ไขเล็กน้อย ฉันหวังว่าคุณจะไม่รังเกียจ ฉันยังลบคำขอบคุณออกและบันทึกเกี่ยวกับคำถามนี้เป็นคำถามแรกของคุณเนื่องจากปกติแล้วสิ่งนั้นไม่ใช่ส่วนหนึ่งของคำถาม SO
David Conrad

11
ฉันเป็น C # การประชุมคือการเพิ่มArgumentNullExceptionในกรณีเช่นนั้น (มากกว่าNullReferenceException) - จริง ๆ แล้วเป็นคำถามที่ดีจริง ๆ ว่าทำไมคุณถึงเพิ่มที่NullPointerExceptionนี่อย่างชัดเจน (แทนที่จะเป็นคนอื่น)
EJoshuaS - Reinstate Monica

21
@EJoshuaS มันเป็นเรื่องถกเถียงกันมากว่าจะโยนIllegalArgumentExceptionหรือNullPointerExceptionโต้เถียงเป็นโมฆะ การประชุม JDK เป็นแบบหลัง
shmosel

33
ปัญหาที่แท้จริงคือพวกเขาโยนข้อผิดพลาดและทิ้งข้อมูลทั้งหมดที่นำไปสู่ข้อผิดพลาดนี้ ดูเหมือนว่านี่คือซอร์สโค้ดจริง ไม่ใช่แม้แต่ข้อความสายเลือดที่เรียบง่าย เสียใจ
Martin Ba

คำตอบ:


254

มีเหตุผลหลายประการที่นึกขึ้นมาได้หลายอย่างเกี่ยวข้องกันอย่างใกล้ชิด:

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

เจตนา: การโยนข้อยกเว้นอย่างชัดเจนทำให้ผู้ดูแลเห็นว่ามีข้อผิดพลาดอย่างจงใจและผู้เขียนก็ตระหนักถึงผลที่จะตามมา

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

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


14
อีกทั้ง: วิธีนี้ตำแหน่งที่มีการโยนข้อยกเว้นถูกผูกเข้ากับตัวแปรเดียวที่ถูกตรวจสอบ ก็ไม่มีข้อยกเว้นอาจเป็นเพราะหนึ่งในหลายตัวแปรที่เป็นโมฆะ
Jens Schauder

45
อีกอันหนึ่ง: ถ้าคุณรอให้ NPE เกิดขึ้นตามธรรมชาติโค้ดบางตัวในระหว่างนั้นอาจเปลี่ยนสถานะของโปรแกรมของคุณผ่านผลข้างเคียง
โทมัส

6
ในขณะที่ตัวอย่างนี้ไม่ได้ทำคุณสามารถใช้ตัวnew NullPointerException(message)สร้างเพื่อชี้แจงสิ่งที่เป็นโมฆะ เหมาะสำหรับผู้ที่ไม่สามารถเข้าถึงซอร์สโค้ดของคุณได้ พวกเขายังทำสิ่งนี้เป็นหนึ่งซับใน JDK 8 ด้วยObjects.requireNonNull(object, message)วิธีการยูทิลิตี้
Robin

3
FAILURE ควรอยู่ใกล้ FAULT "Fail Fast" เป็นมากกว่ากฎง่ายๆ เมื่อใดที่คุณไม่ต้องการพฤติกรรมนี้ พฤติกรรมอื่น ๆ หมายถึงคุณกำลังซ่อนข้อผิดพลาด มี "FAULTS" และ "FAILURES" FAILURE คือเมื่อโปรแกรมนี้ย่อยตัวชี้ NULL และแฮงค์ แต่บรรทัดของรหัสนั้นไม่ใช่ที่ที่ FAULT ตั้งอยู่ ค่า NULL มาจากที่ใดที่หนึ่ง - อาร์กิวเมนต์ของเมธอด ใครผ่านการโต้แย้งนี้ จากบางบรรทัดของรหัสอ้างอิงตัวแปรท้องถิ่น ที่นั่น ... เห็นไหม ที่ดูด ความรับผิดชอบของใครที่ควรได้รับการจัดเก็บค่าที่ไม่ดี? โปรแกรมของคุณควรขัดข้องแล้ว
Noah Spurrier

4
@ โทมัสจุดที่ดี Shmosel: ประเด็นของโทมัสอาจบอกเป็นนัย ๆ ในจุดที่ล้มเหลว แต่มันถูกฝังอยู่ มันเป็นแนวคิดที่สำคัญพอที่จะมีชื่อของตัวเอง: ความล้มเหลวของอะตอมมิก ดู Bloch, Java ที่มีประสิทธิภาพ , รายการที่ 46 มันมีความหมายที่แข็งแกร่งกว่าความล้มเหลวอย่างรวดเร็ว ฉันขอแนะนำให้โทรออกในจุดที่แยกต่างหาก คำตอบที่ยอดเยี่ยมโดยรวม BTW +1
สจวร์ตมาร์ค

40

มันมีไว้เพื่อความชัดเจนความสม่ำเสมอและเพื่อป้องกันการทำงานที่ไม่จำเป็นและไม่จำเป็น

พิจารณาสิ่งที่จะเกิดขึ้นหากไม่มีส่วนคำสั่งที่ด้านบนของวิธีการ มันจะโทรหาเสมอhash(key)และgetNode(hash, key)แม้กระทั่งเมื่อnullผ่านเข้าremappingFunctionมาก่อนที่ NPE จะถูกโยนทิ้งไป

ยิ่งแย่ไปกว่านั้นถ้าifเงื่อนไขเป็นเช่นfalseนั้นเราก็เอาelseสาขาซึ่งไม่ได้ใช้remappingFunctionเลยซึ่งหมายความว่าวิธีการไม่ได้โยน NPE เสมอเมื่อ a nullผ่าน; ไม่ว่าจะขึ้นอยู่กับสถานะของแผนที่

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

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


25

นอกเหนือจากเหตุผลที่ระบุไว้โดยคำตอบที่ยอดเยี่ยมของ @ shmosel ...

ประสิทธิภาพการทำงาน:อาจมี / ได้รับประโยชน์ด้านประสิทธิภาพ (ใน JVM บางตัว) เพื่อโยน NPE อย่างชัดเจนแทนที่จะปล่อยให้ JVM ทำ

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

การทดสอบอย่างชัดเจนสำหรับnullในรหัสจะหลีกเลี่ยงประสิทธิภาพการทำงาน SIGSEGV ในสถานการณ์ที่ NPEs เกิดขึ้นบ่อยครั้ง

(ฉันสงสัยว่านี่จะเป็นการเพิ่มประสิทธิภาพขนาดเล็กที่คุ้มค่าใน JVM สมัยใหม่ แต่อาจเป็นในอดีต)


ความเข้ากันได้:เหตุผลที่เป็นไปได้ที่ไม่มีข้อความในข้อยกเว้นคือเพื่อความเข้ากันได้กับ NPEs ที่ถูกโยนโดย JVM เอง ในการปรับใช้ Java ที่สอดคล้องกับ NPE ที่ส่งออกโดย JVM มีnullข้อความ (Android Java แตกต่างกัน)


20

นอกเหนือจากสิ่งที่คนอื่น ๆ ชี้ให้เห็นแล้วมันก็คุ้มค่าที่จะได้เห็นบทบาทของการประชุมที่นี่ ยกตัวอย่างเช่นใน C # คุณมีแบบแผนเดียวกันในการเพิ่มข้อยกเว้นอย่างชัดเจนในกรณีเช่นนี้ แต่เป็นแบบเฉพาะเจาะจงArgumentNullExceptionซึ่งค่อนข้างเจาะจงกว่า (C # การประชุมคือการที่NullReferenceException มักจะแสดงให้เห็นถึงข้อผิดพลาดบางชนิด - มากเพียงมันไม่ควรที่เคยเกิดขึ้นในรหัสการผลิตที่ได้รับArgumentNullExceptionมักจะไม่เหมือนกัน แต่มันอาจจะเป็นข้อผิดพลาดมากขึ้นตามแนวของ "คุณทำไม่ได้ เข้าใจวิธีการใช้ไลบรารีอย่างถูกต้อง "ชนิดของบั๊ก)

ดังนั้นโดยทั่วไปใน C # NullReferenceExceptionหมายความว่าโปรแกรมของคุณพยายามใช้จริง ๆ ในขณะที่ArgumentNullExceptionมันหมายความว่ามันรับรู้ว่าค่านั้นผิดและไม่ต้องกังวลที่จะใช้มัน ความจริงแล้วอาจแตกต่างกัน (ขึ้นอยู่กับสถานการณ์) เพราะArgumentNullExceptionหมายความว่าวิธีการที่เป็นปัญหายังไม่มีผลข้างเคียง (เนื่องจากไม่สามารถกำหนดเงื่อนไขได้ล่วงหน้า)

อนึ่งหากคุณกำลังเพิ่มบางอย่างเช่นArgumentNullExceptionหรือIllegalArgumentExceptionนั่นเป็นส่วนหนึ่งของการตรวจสอบ: คุณต้องการข้อยกเว้นที่แตกต่างจากที่คุณได้รับ "ปกติ"

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


4
+1 สำหรับย่อหน้ากลาง ฉันจะยืนยันว่ารหัสที่เป็นปัญหาควร 'โยน IllegalArgumentException ใหม่ ("remappingFunction ไม่สามารถเป็นโมฆะ");' ด้วยวิธีนี้จะเห็นได้ทันทีว่ามีอะไรผิดปกติ NPE ที่แสดงนั้นค่อนข้างคลุมเครือ
Chris Parker

1
@ChrisParker ฉันเคยมีความเห็นแบบเดียวกัน แต่ปรากฎว่า NullPointerException มีจุดประสงค์เพื่อแสดงว่าอาร์กิวเมนต์ null ถูกส่งผ่านไปยังวิธีการที่คาดว่าจะเป็นอาร์กิวเมนต์ที่ไม่ใช่ null นอกเหนือจากการตอบสนองแบบรันไทม์เพื่อพยายามแก้ไขปัญหา null จาก javadoc:“ แอปพลิเคชันควรโยนอินสแตนซ์ของคลาสนี้เพื่อระบุการใช้งานที่ผิดกฎหมายอื่น ๆ ของnullวัตถุ” ฉันไม่ได้คลั่งไคล้ แต่ดูเหมือนว่าจะเป็นการออกแบบ
VGR

1
ฉันเห็นด้วย @ChrisParker - ฉันคิดว่าข้อยกเว้นนั้นมีความเฉพาะเจาะจงมากขึ้น (เนื่องจากรหัสไม่เคยพยายามทำสิ่งใด ๆ ที่มีค่ามันจึงจำได้ทันทีว่าไม่ควรใช้) ฉันชอบอนุสัญญา C # ในกรณีนี้ การประชุม C # คือNullReferenceException(เทียบเท่าNullPointerException) หมายความว่ารหัสของคุณพยายามใช้มันจริง ๆ(ซึ่งเป็นข้อผิดพลาดเสมอ - มันไม่ควรเกิดขึ้นในรหัสการผลิต) กับ "ฉันรู้ว่าข้อโต้แย้งนั้นผิดดังนั้นฉันจึงไม่ได้ ลองใช้ดู " นอกจากนี้ยังมีArgumentException(ซึ่งหมายความว่าการโต้แย้งนั้นผิดด้วยเหตุผลอื่น)
EJoshuaS - Reinstate Monica

2
ฉันจะพูดแบบนี้มากฉันโยน IllegalArgumentException ตามที่อธิบายไว้เสมอ ฉันมักจะรู้สึกสะดวกสบายในการประชุมที่น่ารังเกียจเมื่อฉันรู้สึกว่าการประชุมเป็นใบ้
Chris Parker

1
@PieterGeerkens - ใช่เพราะบรรทัด NullPointerException 35 นั้นดีกว่า IllegalArgumentException มาก ("ฟังก์ชั่นต้องไม่เป็นโมฆะ") บรรทัด 35. จริงจังไหม?
Chris Parker

12

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


9

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

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

เห็นได้ชัดว่าการขว้างนายพลNullPointerExceptionเป็นทางเลือกที่แย่จริงๆเพราะมันไม่ได้ส่งสัญญาณการละเมิดสัญญาในตัวของมันเอง IllegalArgumentExceptionจะเป็นทางเลือกที่ดีกว่า


Sidenote:
ฉันไม่รู้ว่า Java อนุญาตให้ใช้ (ฉันสงสัยหรือไม่) แต่โปรแกรมเมอร์ C / C ++ ใช้assert()ในกรณีนี้ซึ่งดีกว่าอย่างมากสำหรับการดีบัก: มันบอกให้โปรแกรมหยุดทำงานทันทีและยากที่สุดเท่าที่จะทำได้ ประเมินสภาพเป็นเท็จ ดังนั้นถ้าคุณวิ่ง

void MyClass_foo(MyClass* me, int (*someFunction)(int)) {
    assert(me);
    assert(someFunction);

    ...
}

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


1
assert something != null;แต่ต้องมีการ-assertionsตั้งค่าสถานะเมื่อเรียกใช้แอป หากไม่มีการ-assertionsตั้งค่าสถานะคำหลักยืนยันจะไม่ทิ้ง AssertionException
Zoe

ผมเห็นด้วยที่ว่าทำไมฉันชอบการประชุม C # นี่ - อ้างอิงโมฆะอาร์กิวเมนต์ไม่ถูกต้องและอาร์กิวเมนต์ null ทั้งหมดทั่วไปบ่งบอกถึงข้อผิดพลาดของบางชนิด แต่พวกเขาบ่งบอกถึงความแตกต่างกันชนิดของโรคจิต "คุณกำลังพยายามใช้การอ้างอิงที่เป็นโมฆะ" มักจะแตกต่างจาก "คุณกำลังใช้ห้องสมุดในทางที่ผิด"
EJoshuaS - Reinstate Monica

7

เป็นเพราะมันเป็นไปได้ที่จะไม่เกิดขึ้นตามธรรมชาติ ลองดูรหัสชิ้นนี้:

bool isUserAMoron(User user) {
    Connection c = UnstableDatabase.getConnection();
    if (user.name == "Moron") { 
      // In this case we don't need to connect to DB
      return true;
    } else {
      return c.makeMoronishCheck(user.id);
    }
}

(แน่นอนว่ามีปัญหามากมายในตัวอย่างนี้เกี่ยวกับคุณภาพของรหัสขออภัยที่ขี้เกียจจินตนาการตัวอย่างที่สมบูรณ์แบบ)

สถานการณ์ที่cจะไม่ถูกใช้จริงและNullPointerExceptionจะไม่ถูกโยนแม้ว่าc == nullจะเป็นไปได้

ในสถานการณ์ที่ซับซ้อนมากขึ้นมันจะไม่ใช่เรื่องง่ายที่จะตามล่าคดีดังกล่าว นี่คือเหตุผลว่าทำไมเช็คทั่วไปถึงif (c == null) throw new NullPointerException()ดีกว่า


เนื้อหาที่ใช้งานได้โดยไม่ต้องมีการเชื่อมต่อฐานข้อมูลเมื่อมันไม่จำเป็นจริงๆเป็นสิ่งที่ดีและรหัสที่เชื่อมต่อกับฐานข้อมูลเพียงเพื่อดูว่าสามารถล้มเหลวในการทำเช่นนั้นมักจะน่ารำคาญมาก
Dmitry Grigoryev

5

มันมีจุดประสงค์เพื่อป้องกันความเสียหายเพิ่มเติมหรือเข้าสู่สถานะที่ไม่สอดคล้องกัน


1

นอกเหนือจากคำตอบที่ยอดเยี่ยมอื่น ๆ ทั้งหมดที่นี่ฉันยังต้องการเพิ่มบางกรณี

คุณสามารถเพิ่มข้อความหากคุณสร้างข้อยกเว้นของคุณเอง

หากคุณโยนของคุณเองNullPointerExceptionคุณสามารถเพิ่มข้อความ (ซึ่งคุณควรแน่นอน!)

ข้อความเริ่มต้นเป็นnullจากและทุกวิธีการที่จะใช้มันตัวอย่างเช่นnew NullPointerException() Objects.requireNonNullหากคุณพิมพ์ null นั้นมันสามารถแปลเป็นสตริงว่าง ...

ค่อนข้างสั้นและไม่เป็นทางการ ...

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

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

การโทรวิธีการรับสายจะทำให้คุณคาดเดาได้

ข้อยกเว้นจะบอกให้คุณทราบในข้อยกเว้นที่เกิดขึ้น พิจารณาแถวต่อไปนี้:

repository.getService(someObject.someMethod());

ถ้าคุณได้ NPE และมันชี้ไปที่แถวนี้อันใดอันหนึ่งrepositoryและsomeObjectว่างเปล่า

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

ข้อผิดพลาดเมื่อประมวลผลอินพุตจำนวนมากควรให้ข้อมูลที่ระบุตัวตน

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

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