ไม่มีการตรวจสอบในการปรับปรุงสำหรับวง


172

วิธีที่ดีที่สุดในการป้องกัน null ใน for for loop ใน Java คืออะไร

ดูเหมือนว่าน่าเกลียด:

if (someList != null) {
    for (Object object : someList) {
        // do whatever
    }
}

หรือ

if (someList == null) {
    return; // Or throw ex
}
for (Object object : someList) {
    // do whatever
}

อาจไม่มีวิธีอื่นใด พวกเขาควรจะวางมันลงในforโครงสร้างของตัวเองหรือไม่ถ้ามันเป็นโมฆะอย่าเรียกใช้ลูป?


2
คุณน่าจะดีกว่าการขว้าง NPE nullไม่เหมือนกับคอลเล็กชันที่ว่างเปล่า
Tom Hawtin - tackline

6
@GregMattes คำถามกุมภาพันธ์เป็นคำถามที่เหมือนกันของเดือนตุลาคมอย่างไร
Val

1
เพียงแค่ต้องใช้ Collections.nonNullElementsIn (... ): stackoverflow.com/a/34913556/5637185
Jeffrey Dilley

คำตอบ:


227

คุณควรตรวจสอบว่าคุณได้รับรายชื่อจากที่ใด

รายการที่ว่างเปล่าเป็นสิ่งที่คุณต้องการเพราะรายการที่ว่างเปล่าจะไม่ล้มเหลว

หากคุณได้รับรายชื่อนี้จากที่อื่นและไม่ทราบว่าใช้ได้หรือไม่คุณสามารถสร้างวิธีการอรรถประโยชน์และใช้มันได้ดังนี้:

for( Object o : safe( list ) ) {
   // do whatever 
 }

และแน่นอนsafeจะเป็น:

public static List safe( List other ) {
    return other == null ? Collections.EMPTY_LIST : other;
}

57
โปรดทราบว่า Collections.emptyList () จะหลีกเลี่ยงการจัดสรรวัตถุพิเศษ (IIRC)
Jon Skeet

7
@ จอน: ฉันมักจะถามตัวเองอยู่เสมอว่าการใช้emptyList java.sun.com/j2se/1.5.0/docs/api/java/util/ อะไรคือ IIRC
OscarRyz

11
IIRC = "ถ้าฉันจำได้ถูกต้อง" และใช่มีอินสแตนซ์ซิงเกิลตันที่ส่งคืนสำหรับการเรียกไปยัง Collections.emptyList () ทั้งหมด
ColinD

สิ่งนี้ ... ไม่ได้ตอบคำถาม ทำไมมันถึงได้รับคำตอบ?
Christopher Wirt

1
@ChristopherWirt เพราะมันจะตอบคำถาม: D
Tarik

100

คุณสามารถเขียนเมธอดตัวช่วยซึ่งส่งคืนลำดับว่างถ้าคุณผ่านเป็นโมฆะ:

public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
    return iterable == null ? Collections.<T>emptyList() : iterable;
}

จากนั้นใช้:

for (Object object : emptyIfNull(someList)) {
}

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


3
ฉันจะเปลี่ยนพารามิเตอร์รายการ Iterable <T> เป็น Iterable <T> iterable เนื่องจากไม่ใช่ทุก iterable ที่เป็นรายการ
Lombo

ระวังการใช้วิธีนี้: เนื่องจากการใช้คลาส Collections การใช้วิธีนี้จะทำให้ list ของคุณไม่เปลี่ยนรูปได้
Tanorix

@tanorix: ในทางใด
Jon Skeet

@JonSkeet คุณจะเห็นว่า emptyList () ของคลาส Collections ส่งคืนรายการที่ไม่เปลี่ยนรูปแบบ: docs.oracle.com/javase/8/docs/api/java/util/ ......ดังนั้นหากผู้ใช้ไม่ต้องการให้รายการของเขาไม่เปลี่ยนรูปสามารถ มีปัญหา
Tanorix

@ Tanorix: แต่ประเด็นของคำถามนี้เกี่ยวกับการทำซ้ำมากกว่าค่าที่ส่งคืน แต่นั่นไม่ได้ปรับเปลี่ยน นั่นเป็นเหตุผลว่าทำไมผลตอบแทนemptyIfNullคือIterable<T>- มีremoveวิธีการที่โชคร้ายIterator<T>แต่นั่นเป็นเพียงแง่มุมที่ไม่แน่นอนของมัน (และหากคุณมีคอลเลกชันที่ว่างเปล่าทำไมคุณถึงพยายามลบอะไรออกจากมัน?) มันไม่ชัดเจนว่าคุณเป็นใคร กำลังคัดค้านที่นี่
Jon Skeet

29

ตอนนี้เป็นปี 2560 แล้วและตอนนี้คุณสามารถใช้ได้ Apache Commons Collections4 ได้แล้ว

การใช้งาน:

for(Object obj : ListUtils.emptyIfNull(list1)){
    // Do your stuff
}

คุณสามารถทำเช็ค null ปลอดภัยเดียวกันกับชั้นเรียนอื่น ๆ CollectionUtils.emptyIfNullที่มีการเก็บ


2
จะทำงานได้แม้ว่าจะสร้างวัตถุรายการที่ไม่จำเป็น CollectionUtils.ifNotEmpty อาจมีความละเอียดมากกว่า แต่มีประสิทธิภาพและรวดเร็วกว่า ไม่ว่ามันจะมีความสำคัญ ...
ลอเรนซ์

2
ในปี 2560 ฉันคาดว่า List.empty ถ้าว่าง (list1)
Dima

3
@Lawrence วิธีนี้ไม่ได้สร้างรายการวัตถุใหม่ แต่ใช้ Collections.emptyList()ภายในซึ่งในทางกลับกันมักจะส่งคืนรายการที่ไม่สามารถแก้ไขได้ที่ว่างเปล่าไว้ล่วงหน้าเดียวกัน
Yoory N.

ถ้าคุณเรียก myobject.getCompanies (). getAddresses () และทั้งสองคืนค่า List และทั้งคู่จะเป็นค่าว่าง
powder366

9

ด้วย Java 8 Optional:

for (Object object : Optional.ofNullable(someList).orElse(Collections.emptyList())) {
    // do whatever
}

1
verbose มากกว่าผู้ประกอบการที่เรียบง่ายอย่างเช่นsomeList != null ? someList : Collections.emptyList()และยังสร้างและทิ้งตัวอย่างของOptionalวัตถุทันที
Yoory N.

2
สัตว์ประหลาดเหล่านี้มีเส้นที่งดงามกว่าคำสั่ง if (someList == null) ง่าย ๆ อย่างไร ลองเขียนใบสมัครธนาคารในบรรทัดเดียว ...
Andreas Panagiotidis

8

ใช้ArrayUtils.nullToEmptyจากcommons-langห้องสมุดสำหรับอาร์เรย์

for( Object o : ArrayUtils.nullToEmpty(list) ) {
   // do whatever 
}

ฟังก์ชันนี้มีอยู่ในcommons-langไลบรารีซึ่งรวมอยู่ในโครงการ Java ส่วนใหญ่

// ArrayUtils.nullToEmpty source code 
public static Object[] nullToEmpty(final Object[] array) {
    if (isEmpty(array)) {
        return EMPTY_OBJECT_ARRAY;
    }
    return array;
}

// ArrayUtils.isEmpty source code
public static boolean isEmpty(final Object[] array) {
    return array == null || array.length == 0;
}

นี่คือคำตอบเดียวกับที่ @OscarRyz แต่เพื่อประโยชน์ของDRYมนต์ฉันเชื่อว่ามันเป็นที่น่าสังเกต ดูหน้าโครงการคอมมอนส์ lang นี่คือเอกสารnullToEmpty API และแหล่งที่มา

รายการ Maven ที่จะรวมcommons-langในโครงการของคุณหากยังไม่ได้ดำเนินการ

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>

น่าเสียดายที่commons-langไม่มีฟังก์ชั่นนี้สำหรับListประเภท ในกรณีนี้คุณจะต้องใช้วิธีการช่วยเหลือตามที่ระบุไว้ก่อนหน้านี้

public static <E> List<E> nullToEmpty(List<E> list)
{
    if(list == null || list.isEmpty())
    {
        return Collections.emptyList();
    }
    return list;
}

7

หากคุณได้รับสิ่งนั้นListจากการเรียกเมธอดที่คุณนำมาใช้อย่าส่งnullคืนค่าว่างListกลับมาที่ว่างเปล่า

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

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


4

ฉันได้แก้ไขคำตอบข้างต้นดังนั้นคุณไม่จำเป็นต้องส่งจาก Object

public static <T> List<T> safeClient( List<T> other ) {
            return other == null ? Collections.EMPTY_LIST : other;
}

แล้วก็เรียกรายการโดย

for (MyOwnObject ownObject : safeClient(someList)) {
    // do whatever
}

คำอธิบาย: MyOwnObject: ถ้าเป็นเช่นList<Integer>นั้น MyOwnObject จะเป็นจำนวนเต็มในกรณีนี้


1

วิธีการได้อย่างมีประสิทธิภาพป้องกัน null ในห่วงอีกประการหนึ่งคือการตัดคอลเลกชันของคุณกับ Google ฝรั่งของเช่นนี้หนึ่งความหวังทำให้เป็นไปได้ของคอลเลกชันที่ว่างเปล่าได้อย่างมีประสิทธิภาพที่ชัดเจนตั้งแต่ลูกค้าจะคาดว่าจะตรวจสอบว่าเป็นของสะสมที่มีอยู่ด้วยOptional<T>Optional.isPresent()


1

สำหรับทุกคนที่ไม่สนใจในการเขียนวิธีการเพื่อความปลอดภัยคง null ของตัวเองคุณสามารถใช้: org.apache.commons.lang.ObjectUtils.defaultIfNull(Object, Object)คอมมอน-lang ตัวอย่างเช่น:

    for (final String item : 
    (List<String>)ObjectUtils.defaultIfNull(items, Collections.emptyList())) { ... }

ObjectUtils.defaultIfNull JavaDoc


สำหรับฉันคำตอบนี้งดงามที่สุด
Truong Nguyen

0

ใช้CollectionUtils.isEmpty(Collection coll)วิธีการตรวจสอบว่าเป็นโมฆะปลอดภัยถ้าคอลเลกชันที่ระบุว่างเปล่า

สำหรับสิ่งนี้ import org.apache.commons.collections.CollectionUtilsสำหรับเรื่องนี้

Maven พึ่งพา

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>

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