การสะท้อนอาร์เรย์ Java: isArray เทียบกับ instanceof


คำตอบ:


203

ในกรณีส่วนใหญ่คุณควรใช้instanceofโอเปอเรเตอร์เพื่อทดสอบว่าวัตถุนั้นเป็นอาร์เรย์หรือไม่

โดยทั่วไปแล้วคุณจะทดสอบชนิดของวัตถุก่อนที่จะทำการดาวน์โหลดไปยังชนิดเฉพาะซึ่งเป็นที่รู้จักในเวลารวบรวม ยกตัวอย่างเช่นบางทีคุณอาจจะเขียนรหัสบางอย่างที่สามารถทำงานร่วมกับหรือInteger[] int[]คุณต้องการปกป้องการแสดงของคุณด้วยinstanceof:

if (obj instanceof Integer[]) {
    Integer[] array = (Integer[]) obj;
    /* Use the boxed array */
} else if (obj instanceof int[]) {
    int[] array = (int[]) obj;
    /* Use the primitive array */
} else ...

ที่ระดับ JVM ตัวinstanceofดำเนินการแปลเป็นรหัส"instanceof"ไบต์เฉพาะซึ่งได้รับการปรับให้เหมาะสมในการใช้งาน JVM ส่วนใหญ่

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

มีสองกรณีพิเศษคือการอ้างอิงที่เป็นโมฆะและการอ้างอิงไปยังอาร์เรย์ดั้งเดิม

อ้างอิงโมฆะจะทำให้เกิดการinstanceofที่จะส่งผลfalseในขณะที่พ่นisArrayNullPointerException

นำไปใช้กับอาร์เรย์ดั้งเดิมinstanceofจะให้ผลตอบแทนfalseเว้นแต่ว่าประเภทส่วนประกอบทางด้านขวาของตัวถูกดำเนินการตรงกับประเภทส่วนประกอบ ในทางตรงกันข้ามisArray()จะกลับมาtrueสำหรับองค์ประกอบประเภทใด ๆ


7
ใช่ แต่จะมีความแตกต่างกันมากแค่ไหน? นั่นฟังดูเป็นการเพิ่มประสิทธิภาพแบบไมโครสำหรับฉัน
Michael Myers

2
@Dims หากคุณยืนยันว่าobj instanceof int[]ผลตอบแทนfalseเมื่อคุณกำหนดให้int[]กับobjคุณจะเข้าใจผิด
erickson

4
ขอโทษฉันหมายความว่าobj instanceof Object[]อัตราผลตอบแทนถ้าfalse Object obj = new int[7]
Dims

3
ถูกต้องใน Java ชนิดข้อมูลดั้งเดิมไม่ใช่วัตถุและไม่ขยายjava.lang.Objectดังนั้นจึงเหมาะสม แต่instanceofยังสามารถใช้ทดสอบอาร์เรย์ดั้งเดิมได้
erickson

4
-1: โดยทั่วไปเนื่องจากอาร์เรย์ดั้งเดิมคือการเรียกisArray()ใช้อาร์เรย์ควรใช้ ในกรณีพิเศษทั่วไปที่มีเพียงอาร์เรย์ของวัตถุเท่านั้นinstanceofเป็นทางเลือกที่มีประสิทธิภาพสูง
Sam Harwell

33

ในกรณีหลังถ้า obj เป็นโมฆะคุณจะไม่ได้รับ NullPointerException แต่เป็นเท็จ


8

ถ้าobjเป็นประเภทint[]พูดแล้วว่าจะมีอาร์เรย์แต่ไม่เป็นตัวอย่างของClass ดังนั้นสิ่งที่คุณต้องการจะทำอย่างไรกับObject[] หากคุณกำลังจะโยนมันทิ้งไปกับobj หากคุณกำลังจะสะท้อนการใช้แล้วใช้instanceof.getClass().isArray()


4

getClass().isArray() ช้ากว่าอย่างมากสำหรับ Sun Java 5 หรือ 6 JRE มากกว่าบน IBM

clazz.getName().charAt(0) == '['Sun JVM ใช้งานได้เร็วกว่ามาก


10
คุณมีสถิติกรณีศึกษาหรือหลักฐานอื่น ๆ ที่คุณสามารถลิงค์ไปได้หรือไม่?
David Citron

4

ฉันเพิ่งพบปัญหาในการอัปเกรดแอปพลิเคชัน Groovy จาก JDK 5 เป็น JDK 6 การใช้isArray()ล้มเหลวใน JDK6:

MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...

เปลี่ยนเป็นinstanceof Object[]แก้ไขสิ่งนี้


มันไม่สมเหตุสมผล isArrayเป็นวิธีการที่Classไม่Typeดังนั้นแน่นอนGenericArrayTypeImplไม่มีวิธีการที่ และgetClassไม่สามารถกลับมาเป็นที่ไม่ใช่Class Typeเพื่อให้คุณ (หรือ Groovy ??) จะต้องมีบางอย่างผิดปกติเสร็จแล้วจะได้รับนี้เช่นสมมติว่าทุกคนเป็นType Class
kaqqao

3

การสะท้อนอาร์เรย์ Java มีไว้สำหรับกรณีที่คุณไม่มีอินสแตนซ์ของ Class ที่พร้อมใช้งานเพื่อเปิด "instanceof" ตัวอย่างเช่นหากคุณกำลังเขียนกรอบงานการฉีดบางประเภทนั้นจะแทรกค่าลงในอินสแตนซ์ใหม่ของคลาสเช่น JPA คุณต้องใช้ฟังก์ชัน isArray ()

ฉัน blogged เกี่ยวกับเรื่องนี้ก่อนหน้านี้ในเดือนธันวาคม http://blog.adamsbros.org/2010/12/08/java-array-reflection/


2

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


เอ่อ "อินสแตนซ์ของ" เป็นภาพสะท้อน (หรืออย่างน้อยก็วิปัสสนา) แต่ฉันเข้าใจประเด็นของคุณ
David Citron

นอกจากนี้โดยทั่วไปจะช้ากว่า
นักฟิสิกส์บ้า

0

ไม่มีความแตกต่างในพฤติกรรมที่ฉันสามารถค้นหาระหว่างทั้งสอง (นอกเหนือจากกรณีที่ชัดเจนเป็นโมฆะ) สำหรับเวอร์ชั่นที่ฉันชอบฉันจะเลือกรุ่นที่สอง มันเป็นวิธีมาตรฐานในการทำเช่นนี้ใน Java

หากมันทำให้ผู้อ่านสับสนกับรหัสของคุณ (เพราะString[] instanceof Object[]เป็นจริง) คุณอาจต้องการใช้คำสั่งแรกเพื่อให้ชัดเจนยิ่งขึ้นถ้าผู้ตรวจสอบโค้ดถามเกี่ยวกับมัน

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