วัตถุ == null หรือ null == วัตถุ?


97

ฉันได้ยินจากใครบางคนที่null == objectดีกว่าobject == null ตรวจสอบ

เช่น :

void m1(Object obj ) {
   if(null == obj)  // Is this better than object == null ? Why ?
       return ;
   // Else blah blah
}

มีเหตุผลอะไรหรือนี่เป็นอีกตำนาน? ขอบคุณที่ช่วยเหลือ.


2
null == objectเรียกได้ว่าเป็นสภาพ Yoda
Ciro Santilli 郝海东冠状病六四事件法轮功

คำตอบ:


140

นี่อาจเป็นนิสัยที่เรียนรู้จาก C เพื่อหลีกเลี่ยงการพิมพ์ผิดประเภทนี้ (เดี่ยว=แทนที่จะเป็นสองเท่า==):

if (object = null) {

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


33

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

สิ่งที่ไม่ได้กล่าวถึงคือหลาย ๆ คน (รวมถึงตัวฉันเองด้วย) พบว่าif (variable == constant)แบบฟอร์มนี้อ่านได้ง่ายขึ้นซึ่งเป็นวิธีการแสดงความเป็นตัวเองที่เป็นธรรมชาติมากขึ้น นี่เป็นเหตุผลที่จะไม่คัดลอกการประชุมแบบสุ่มสี่สุ่มห้าจาก C. คุณควรตั้งคำถามเกี่ยวกับการปฏิบัติ (ดังที่คุณทำอยู่ที่นี่ :) ก่อนที่จะตั้งสมมติฐานว่าสิ่งที่อาจเป็นประโยชน์ในสภาพแวดล้อมหนึ่งมีประโยชน์ในอีกสภาพแวดล้อมหนึ่ง


28

นี้ไม่ได้เป็นของค่ามากในชวา (1.5+) Booleanยกเว้นเมื่อชนิดของวัตถุที่เป็น ในกรณีนี้สิ่งนี้ยังคงมีประโยชน์

if (object = null)จะไม่ทำให้การคอมไพล์ล้มเหลวใน Java 1.5+ หากออบเจ็กต์เป็นBooleanแต่จะโยนNullPointerExceptionรันไทม์


2
สำหรับชนิดที่ไม่ใช่บูลีนโค้ดจะไม่คอมไพล์เนื่องจากประเภทของนิพจน์ "object = null" จะไม่เป็นบูลีน เนื่องจากการชกมวยอัตโนมัติจะคอมไพล์สำหรับบูลีน
Chandra Sekar

9

ใน Java ไม่มีเหตุผลที่ดี

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

if (o = null)

จะไม่รวบรวม

ครั้งเดียวที่อาจมีความสำคัญใน Java คือถ้าตัวแปรเป็นบูลีน:

int m1(boolean x)
{
    if (x = true)  // oops, assignment instead of equality

9

สิ่งนี้เกี่ยวข้องอย่างใกล้ชิดกับ:

if ("foo".equals(bar)) {

ซึ่งสะดวกหากคุณไม่ต้องการจัดการกับ NPE:

if (bar!=null && bar.equals("foo")) {

5

เคล็ดลับนี้ควรป้องกันv = nullการพิมพ์ผิด

แต่ Java อนุญาตให้ใช้นิพจน์บูลีนเท่านั้นที่เป็นif()เงื่อนไขเพื่อให้เคล็ดลับไม่สมเหตุสมผลนักคอมไพเลอร์ก็จะพบการพิมพ์ผิดเหล่านั้นอยู่ดี

ยังคงเป็นเคล็ดลับที่มีค่าสำหรับรหัส C / C ++


3

ด้วยเหตุผลเดียวกับที่คุณทำใน C; ที่ได้รับมอบหมายคือการแสดงออกเพื่อให้คุณใส่ตัวอักษรด้านซ้ายเพื่อให้คุณไม่สามารถเขียนทับมันถ้าคุณตั้งใจใช้แทน===


1
ไม่คอมไพเลอร์ Java จะตรวจจับการพิมพ์ผิดตามลำดับที่คุณต้องการ
vava

3

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

ชอบ:

 String b = null;
 "constant".equals(b);  // result to false
 b.equals("constant");  // NullPointerException
 b != null && b.equals("constant");  // result to false

2

เป็นการเขียนเงื่อนไข Yoda ในลักษณะที่แตกต่างกัน

ใน Java

String myString = null;
if (myString.equals("foobar")) { /* ... */ } //Will give u null pointer

สภาพโยดา

String myString = null;
if ("foobar".equals(myString)) { /* ... */ } // will be false 

1

เปรียบเทียบกับรหัสต่อไปนี้:

    String pingResult = "asd";
    long s = System.nanoTime ( );
    if ( null != pingResult )
    {
        System.out.println ( "null != pingResult" );
    }
    long e = System.nanoTime ( );
    System.out.println ( e - s );

    long s1 = System.nanoTime ( );
    if ( pingResult != null )
    {
        System.out.println ( "pingResult != null" );
    }
    long e1 = System.nanoTime ( );
    System.out.println ( e1 - s1 );

ผลลัพธ์ (หลังจากการดำเนินการหลายครั้ง):

null != pingResult
325737
pingResult != null
47027

ดังนั้นจึงpingResult != nullเป็นผู้ชนะ


1

เนื่องจากคุณสมบัติการสับเปลี่ยนของมันความแตกต่างเพียงอย่างเดียวระหว่างobject == nullและnull == object( เวอร์ชัน Yoda ) คือลักษณะของการรับรู้ : ผู้อ่านอ่านและย่อยรหัสอย่างไร ฉันไม่รู้คำตอบที่ชัดเจน แต่ฉันรู้ว่าโดยส่วนตัวแล้วฉันชอบเปรียบเทียบวัตถุที่ฉันกำลังตรวจสอบกับสิ่งอื่นมากกว่าเปรียบเทียบสิ่งอื่นกับวัตถุที่ฉันกำลังตรวจสอบหากมันสมเหตุสมผล เริ่มต้นด้วยหัวเรื่องจากนั้นตามด้วยค่าที่จะเปรียบเทียบ

ในภาษาอื่น ๆ รูปแบบการเปรียบเทียบนี้มีประโยชน์มากกว่า

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

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