จะดูว่าวัตถุเป็นอาร์เรย์โดยไม่ใช้การสะท้อนได้อย่างไร?


99

ฉันจะดูใน Java ได้อย่างไรว่า Object เป็นอาร์เรย์โดยไม่ใช้การสะท้อน และฉันจะทำซ้ำรายการทั้งหมดโดยไม่ใช้การสะท้อนกลับได้อย่างไร

ฉันใช้ Google GWT ดังนั้นฉันจึงไม่ได้รับอนุญาตให้ใช้การสะท้อนกลับ :(

ฉันชอบที่จะใช้วิธีการต่อไปนี้โดยไม่ต้องใช้การสะท้อนกลับ:

private boolean isArray(final Object obj) {
  //??..
}

private String toString(final Object arrayObject) {
  //??..
}

BTW: ฉันไม่ต้องการใช้ JavaScript เพื่อให้สามารถใช้ในสภาพแวดล้อมที่ไม่ใช่ GWT ได้

คำตอบ:


251

คุณสามารถใช้ได้ Class.isArray()

public static boolean isArray(Object obj)
{
    return obj!=null && obj.getClass().isArray();
}

สิ่งนี้ใช้ได้กับทั้งอาร์เรย์วัตถุและชนิดดั้งเดิม

สำหรับ toString ลองดูที่Arrays.toString. คุณจะต้องตรวจสอบประเภทอาร์เรย์และเรียกใช้toStringวิธีการที่เหมาะสม


2
obj.getClass().getComponentType()เวิเพิ่มว่าคุณสามารถหาชนิดอาร์เรย์โดยใช้
Steve Chambers

68

คุณสามารถใช้instanceof.

JLS 15.20.2 Type Comparison Operator instanceof

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

ในขณะรันผลลัพธ์ของตัวinstanceofดำเนินการคือtrueถ้าค่าของRelationalExpressionไม่ใช่nullและการอ้างอิงสามารถส่งไปยังReferenceType ได้โดยไม่ต้องเพิ่มค่าClassCastException. falseมิฉะนั้นผลที่ได้คือ

นั่นหมายความว่าคุณสามารถทำสิ่งนี้ได้:

Object o = new int[] { 1,2 };
System.out.println(o instanceof int[]); // prints "true"        

คุณจะต้องตรวจสอบว่าวัตถุที่เป็นinstanceof boolean[], byte[], short[], char[], int[], long[], float[], double[]หรือObject[]ถ้าคุณต้องการที่จะตรวจสอบทุกประเภทอาร์เรย์

นอกจากนี้ an int[][]เป็นinstanceof Object[]ดังนั้นขึ้นอยู่กับว่าคุณต้องการจัดการอาร์เรย์ที่ซ้อนกันอย่างไรก็อาจมีความซับซ้อนได้

สำหรับtoString, java.util.ArraysมีtoString(int[])และ overloads อื่น ๆ ที่คุณสามารถใช้ นอกจากนี้ยังมีdeepToString(Object[])สำหรับอาร์เรย์ที่ซ้อนกัน

public String toString(Object arr) {
   if (arr instanceof int[]) {
      return Arrays.toString((int[]) arr);
   } else //...
}

มันจะซ้ำซากมาก (แต่java.util.Arraysก็ซ้ำซากมาก ) แต่นั่นเป็นวิธีที่อยู่ใน Java ที่มีอาร์เรย์

ดูสิ่งนี้ด้วย


ขอบคุณที่ไม่รู้ว่ามันง่ายขนาดนั้น ไม่สามารถใช้ความคิดที่ตรงไปตรงมากับ T [] :(
edbras

2
BTW: ฉันสังเกตเห็นอีกวิธีที่ดีในการค้นพบว่ามีบางอย่างเป็นอาร์เรย์ Class.isArray () (ใช้ใน Arrays.deepToString ())
edbras

@edbras: ใช่นั่นคือสิ่งที่ Steve Kuo พูดไว้ด้านล่าง วิธีแก้ปัญหาของฉันใช้โครงสร้างทางภาษาล้วน ๆ แทนการเรียก API
polygenelubricants

ใช้งานได้ดีฉันไม่ได้ใช้อินสแตนซ์ของ แต่ getClass เป็นการเปรียบเทียบ สิ่งที่ชอบ: if (array.getClass == int []. class) อาร์เรย์ {Arrays.toString ((int [])); } ขอบคุณทุกท่าน ..
edbras

@edbras: นั่นเป็นอย่างไรjava.util.Arraysใช่ ฉันเห็นว่าคุณกำลังอ่านรหัสที่ฉันเชื่อมโยงไป
polygenelubricants

36

หนึ่งสามารถเข้าถึงแต่ละองค์ประกอบของอาร์เรย์แยกกันโดยใช้รหัสต่อไปนี้:

Object o=...;
if ( o.getClass().isArray() ) {
    for(int i=0; i<Array.getLength(o); i++){
        System.out.println(Array.get(o, i));
    }
}

โปรดสังเกตว่าไม่จำเป็นที่จะต้องทราบว่าอาร์เรย์พื้นฐานเป็นแบบใดเนื่องจากจะใช้ได้กับอาร์เรย์ใด ๆ


2
isArray()ได้รับการกล่าวถึงอย่างเพียงพอแล้วในคำตอบที่โพสต์ไว้ 4 ปีก่อนหน้านี้
Jason C

15
คำตอบนี้ดีมากเพราะแสดงให้เราเห็นถึงวิธีการรับขนาดของอาร์เรย์และการดึงข้อมูลองค์ประกอบโดยไม่ต้องรู้ประเภทเนื้อหา ฉันแน่ใจว่าคนส่วนใหญ่ไม่เคยเขียนโค้ดแบบนี้มาก่อน
Christopher Yang

@MaartenBodewes - ฉันจะใช้ลิงก์นี้เพื่อตัดสินใจว่า "ไม่ใช้การสะท้อน" หมายถึงอะไรสำหรับ GWT
Stephen C

10

ไม่มีความสัมพันธ์ของการพิมพ์ย่อยระหว่างอาร์เรย์ของชนิดดั้งเดิมหรือระหว่างอาร์เรย์ของชนิดดั้งเดิมและอาร์เรย์ของประเภทการอ้างอิง ดูJLS 4.10.3

ดังนั้นสิ่งต่อไปนี้จึงไม่ถูกต้องเนื่องจากเป็นการทดสอบเพื่อดูว่าobjเป็นอาร์เรย์ประเภทใด :

// INCORRECT!
public boolean isArray(final Object obj) {
    return obj instanceof Object[];
}

โดยเฉพาะอย่างยิ่งจะไม่ทำงานหากobjเป็นอาร์เรย์แบบดั้งเดิม 1 มิติ (ใช้งานได้กับอาร์เรย์ดั้งเดิมที่มีขนาดสูงกว่าเนื่องจากอาร์เรย์ทุกประเภทเป็นประเภทย่อยของObjectแต่ในกรณีนี้เป็นที่สงสัย)

ฉันใช้ Google GWT ดังนั้นฉันจึงไม่ได้รับอนุญาตให้ใช้การสะท้อนกลับ :(

ทางออกที่ดีที่สุด (สำหรับisArrayส่วนอาร์เรย์ของคำถาม) ขึ้นอยู่กับสิ่งที่นับว่า "ใช้การสะท้อน"

  • ใน GWT การโทรobj.getClass().isArray()ไม่นับเป็นการใช้การสะท้อน1ดังนั้นจึงเป็นทางออกที่ดีที่สุด

  • มิฉะนั้นวิธีที่ดีที่สุดในการหาว่าวัตถุมีประเภทอาร์เรย์หรือไม่คือการใช้ลำดับของinstanceofนิพจน์

    public boolean isArray(final Object obj) {
        return obj instanceof Object[] || obj instanceof boolean[] ||
           obj instanceof byte[] || obj instanceof short[] ||
           obj instanceof char[] || obj instanceof int[] ||
           obj instanceof long[] || obj instanceof float[] ||
           obj instanceof double[];
    }
    
  • นอกจากนี้คุณยังสามารถลองใช้ชื่อคลาสของอ็อบเจ็กต์ดังต่อไปนี้ แต่การเรียกใช้obj.getClass()นั้นอยู่ติดกับการสะท้อน

    public boolean isArray(final Object obj) {
        return obj.getClass().toString().charAt(0) == '[';
    }
    

1 - แม่นยำยิ่งขึ้นClass.isArrayวิธีนี้แสดงรายการที่รองรับโดย GWT ในหน้านี้


0

คุณสามารถสร้างระดับประโยชน์ในการตรวจสอบว่าชั้นหมายใด ๆคอลเลกชัน , แผนที่หรืออาร์เรย์

  public static boolean isCollection(Class<?> rawPropertyType) {
        return Collection.class.isAssignableFrom(rawPropertyType) || 
               Map.class.isAssignableFrom(rawPropertyType) || 
               rawPropertyType.isArray();
 }

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