Java: วิธีตรวจสอบว่าวัตถุเป็นโมฆะหรือไม่?


89

ฉันกำลังสร้างแอปพลิเคชันที่ดึงรูปภาพจากเว็บ ในกรณีที่ไม่สามารถดึงภาพได้ควรใช้ภาพในเครื่องอื่น

ขณะพยายามดำเนินการบรรทัดต่อไปนี้:

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable.equals(null)) {
  drawable = getRandomDrawable();
}

บรรทัดถ้า (drawable.equals (null)) จะแสดงข้อยกเว้นหาก drawable เป็นโมฆะ

ไม่มีใครรู้ว่าควรตรวจสอบค่า drawable อย่างไรเพื่อไม่ให้เกิดข้อยกเว้นในกรณีที่เป็นโมฆะและดึงข้อมูลภาพในเครื่อง (เรียกใช้ drawable = getRandomDrawable ())?


23
ใช้if (drawable == null) การเรียกใช้เมธอดใด ๆ บนวัตถุ NULL คือ NullPointerException
diciu

3
ทำไมคุณไม่เขียนคำตอบปกติแทนความคิดเห็น diciu?
deamon

@JaredBurrows อย่าแก้ไขรหัสในคำถามในลักษณะที่เอาชนะวัตถุประสงค์ของคำถาม!
Gilles 'SO- หยุดชั่ว'

@Gilles อ่านความคิดเห็นบรรณาธิการของฉันฉันทำให้รหัสอ่านง่ายขึ้น
Jared Burrows

@JaredBurrows ไม่การแก้ไขของคุณไม่ใช่การเปลี่ยนแปลง "การจัดรูปแบบ" คุณเปลี่ยนรหัสที่ไม่ทำงานซึ่งเป็นเป้าหมายของคำถามเป็นรหัสการทำงานซึ่งทำให้คำถามสงสัย
Gilles 'SO- หยุดชั่ว'

คำตอบ:


35

แก้ไข Java 8 Solution:

final Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

คุณสามารถประกาศได้drawable finalในกรณีนี้

ตามที่ Chasmo ชี้ให้เห็นว่า Android ไม่รองรับ Java 8 ในขณะนี้ ดังนั้นวิธีนี้จึงทำได้ในบริบทอื่นเท่านั้น


7
อาจไม่ใช่ความคิดที่ดีคุณกำลังจะกลับไปที่ Fortran 60 ซึ่งมีการประเมินเงื่อนไขทั้งสองด้านจากนั้นจะใช้เพียงด้านเดียว สิ่งนี้จะไม่ดีหากสาขาที่ไม่ได้ใช้มีการคำนวณใด ๆ ซึ่งเป็นความจริงเกือบตลอดเวลาดังนั้นจึงไม่ใช่วิธีที่มีประโยชน์โดยทั่วไป ฉันจะย้ายเงื่อนไขไปที่Commonชั้นเรียนและอนุญาตให้คุณระบุ URL สำรองและรักษาความรับผิดชอบร่วมกัน
Pete Kirkham

1
ตอนนี้ตัวอย่างถูกเขียนใหม่ทั้งหมดใน Java 8 ดังนั้นโซลูชันของฉันจึงไม่ได้รับผลกระทบจากการประเมินที่ไร้ประโยชน์อีกต่อไป (ตามที่ @PeteKirkham ชี้ให้เห็นในโซลูชันดั้งเดิมของฉัน)
deamon

1
Android ไม่รองรับ Java 8 โดยรองรับเฉพาะ Java 7 เท่านั้น (หากคุณมี kitkat) และยังไม่มีการเรียกใช้แบบไดนามิกมีเพียงน้ำตาลไวยากรณ์ใหม่เท่านั้น นอกจากนั้นOptional.ofหมายความว่าค่าไม่เป็นโมฆะดังนั้นจึงorElseGetไม่จำเป็น คุณควรใช้Optional.ofNullableในกรณีนี้
Martin Seeler

181
Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable == null) {
    drawable = getRandomDrawable();
}

equals()วิธีการตรวจสอบค่าความเสมอภาคซึ่งหมายความว่ามันเปรียบเทียบเนื้อหาของวัตถุสอง เนื่องจากnullไม่ใช่วัตถุสิ่งนี้จึงขัดข้องเมื่อพยายามเปรียบเทียบเนื้อหาของวัตถุของคุณกับเนื้อหาของnull.

==การตรวจสอบผู้ประกอบการสำหรับการอ้างอิงความเสมอภาคซึ่งหมายความว่ามันดูไม่ว่าจะเป็นวัตถุทั้งสองเป็นจริงวัตถุเดียวกันมาก สิ่งนี้ไม่ต้องการให้วัตถุมีอยู่จริง สองวัตถุที่ไม่มีอยู่จริง ( nullการอ้างอิง) จะเท่ากันด้วย


56
ฉันต้องการเพิ่มเป็นเคล็ดลับที่มีคุณค่ามาก: หากคุณมีสายหรือค่าคงที่เพื่อเปรียบเทียบเสมอทำให้พวกเขาเป็นครั้งแรกในเท่ากับข้อ (if ("coyote" .equals (myDogString))) จะดีกว่า (if (myDogString.equals ("coyote"))) มากเพราะในกรณีที่สอง myDogString อาจเป็นโมฆะและพ่น NPE ในขณะที่ในกรณีแรกไม่ ไม่สำคัญว่า myDogString เป็นโมฆะ
Thorsten S.

21
รู้จักกันในชื่อ Yoda condition: "if a coyote, the dog is ... "
Thomas

1
ฉันต้องการเพิ่มด้วยว่าเนื่องจาก Java 7 มีเมธอด Objects.equals () ดังนั้นคุณจึงไม่สนใจเกี่ยวกับไวยากรณ์ของ Yoda
maryokhin

22

ฉันใช้แนวทางนี้:

if (null == drawable) {
  //do stuff
} else {
  //other things
}

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

ด้วยการไปถึงเหตุผลที่คุณไม่สามารถเรียก.equals()บนวัตถุซึ่งอาจจะเป็นnull; หากการอ้างอิงวัตถุที่คุณมี (กล่าวคือ 'drawable') เป็นจริงnullมันจะไม่ชี้ไปที่วัตถุบนฮีป ซึ่งหมายความว่าไม่มีวัตถุใดบนฮีปที่การเรียกร้องจะequals()ประสบความสำเร็จ

ขอให้โชคดี!


4
ฉันชอบโครงสร้าง if (<constant> == <variable>) เพื่อป้องกันตัวเองจากการมอบหมายงานโดยไม่ได้ตั้งใจ
สก็อต


6
drawable.equals(null)

บรรทัดด้านบนเรียกเมธอด "equals (... )" บนวัตถุที่วาดได้

ดังนั้นเมื่อ drawable ไม่เป็นโมฆะและเป็นวัตถุจริงทุกอย่างก็จะไปด้วยกันเมื่อเรียกเมธอด "equals (null)" ก็จะส่งคืน "false"

แต่เมื่อ "drawable" เป็นโมฆะหมายความว่าการเรียกเมธอด "equals (... )" บนวัตถุว่างหมายถึงการเรียกใช้เมธอดบนวัตถุที่ไม่มีอยู่จริงดังนั้นจึงพ่น "NullPointerException"

ในการตรวจสอบว่ามีออบเจ็กต์อยู่หรือไม่และไม่เป็นโมฆะให้ใช้สิ่งต่อไปนี้

if(drawable == null) {
    ...
    ...
}

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

null == null

ถูกต้อง



0

อาจมีประสิทธิภาพมากกว่าเล็กน้อยในการจับ NullPointerException วิธีการข้างต้นหมายความว่ารันไทม์ตรวจสอบพอยน์เตอร์ว่างสองครั้ง


1
if x == nullโซลูชันการเช็คอินสองครั้งอยู่ที่ไหน?
deamon

หลังจากคำสั่ง if รันไทม์จะตรวจสอบอีกครั้งเพื่อหาตัวชี้ค่าว่างเมื่อวัตถุถูกใช้ ฉันไม่รู้ว่าสิ่งนี้ได้รับการปรับให้เหมาะสมโดยคอมไพเลอร์หรือไม่
Tom R

4
สิ่งนี้สวนทางกับภูมิปัญญาดั้งเดิมโดยใช้ข้อยกเว้นเป็นการควบคุมกระแส
James

1
ข้อยกเว้นมีราคาแพงมากเนื่องจากต้องสร้าง stacktrace ทั้งหมด
deamon

0

ใช้google guava libsเพื่อจัดการ is-null-check (การอัปเดตของ deamon)

Drawable drawable = Optional.of(Common.getDrawableFromUrl(this, product.getMapPath())).or(getRandomDrawable());

Optionalวันนี้ใช้ Java 8 ดีกว่า
deamon

-1

เพียงเพื่อให้แนวคิดบางอย่างแก่นักพัฒนาซอร์ส oracle Java :-)

โซลูชันมีอยู่แล้วใน. Net และอ่านได้ง่ายขึ้นมาก!

ใน Visual Basic .Net

Drawable drawable 
    = If(Common.getDrawableFromUrl(this, product.getMapPath())
        ,getRandomDrawable()
        )

ใน C #

Drawable drawable 
    = Common.getDrawableFromUrl(this, product.getMapPath() 
        ?? getRandomDrawable();

โซลูชันเหล่านี้มีประสิทธิภาพในฐานะโซลูชัน Java เสริม (สตริงดีฟอลต์จะได้รับการประเมินก็ต่อเมื่อค่าดั้งเดิมเป็นค่าว่าง) โดยไม่ต้องใช้นิพจน์แลมบ์ดาเพียงแค่เพิ่มตัวดำเนินการใหม่

เพื่อให้เห็นความแตกต่างอย่างรวดเร็วกับโซลูชัน Java ฉันได้เพิ่มโซลูชัน Java 2 ตัว

การใช้ทางเลือกใน Java

Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

ใช้ {} ใน Java

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable != null)
    {
    drawable = getRandomDrawable();
    }

โดยส่วนตัวแล้วฉันชอบ VB.Net แต่ฉันชอบ?? C#หรือif {}วิธีแก้ปัญหาใน Java ... แล้วคุณล่ะ?

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