มีการตั้งค่าหรือความแตกต่างพฤติกรรมระหว่างการใช้:
if(obj.getClass().isArray()) {}
และ
if(obj instanceof Object[]) {}
?
มีการตั้งค่าหรือความแตกต่างพฤติกรรมระหว่างการใช้:
if(obj.getClass().isArray()) {}
และ
if(obj instanceof Object[]) {}
?
คำตอบ:
ในกรณีส่วนใหญ่คุณควรใช้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สำหรับองค์ประกอบประเภทใด ๆ
obj instanceof int[]ผลตอบแทนfalseเมื่อคุณกำหนดให้int[]กับobjคุณจะเข้าใจผิด
obj instanceof Object[]อัตราผลตอบแทนถ้าfalse Object obj = new int[7]
java.lang.Objectดังนั้นจึงเหมาะสม แต่instanceofยังสามารถใช้ทดสอบอาร์เรย์ดั้งเดิมได้
isArray()ใช้อาร์เรย์ควรใช้ ในกรณีพิเศษทั่วไปที่มีเพียงอาร์เรย์ของวัตถุเท่านั้นinstanceofเป็นทางเลือกที่มีประสิทธิภาพสูง
ในกรณีหลังถ้า obj เป็นโมฆะคุณจะไม่ได้รับ NullPointerException แต่เป็นเท็จ
ถ้าobjเป็นประเภทint[]พูดแล้วว่าจะมีอาร์เรย์แต่ไม่เป็นตัวอย่างของClass ดังนั้นสิ่งที่คุณต้องการจะทำอย่างไรกับObject[] หากคุณกำลังจะโยนมันทิ้งไปกับobj หากคุณกำลังจะสะท้อนการใช้แล้วใช้instanceof.getClass().isArray()
getClass().isArray() ช้ากว่าอย่างมากสำหรับ Sun Java 5 หรือ 6 JRE มากกว่าบน IBM
clazz.getName().charAt(0) == '['Sun JVM ใช้งานได้เร็วกว่ามาก
ฉันเพิ่งพบปัญหาในการอัปเกรดแอปพลิเคชัน 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
การสะท้อนอาร์เรย์ Java มีไว้สำหรับกรณีที่คุณไม่มีอินสแตนซ์ของ Class ที่พร้อมใช้งานเพื่อเปิด "instanceof" ตัวอย่างเช่นหากคุณกำลังเขียนกรอบงานการฉีดบางประเภทนั้นจะแทรกค่าลงในอินสแตนซ์ใหม่ของคลาสเช่น JPA คุณต้องใช้ฟังก์ชัน isArray ()
ฉัน blogged เกี่ยวกับเรื่องนี้ก่อนหน้านี้ในเดือนธันวาคม http://blog.adamsbros.org/2010/12/08/java-array-reflection/
หากคุณมีทางเลือกระหว่างสารละลายสะท้อนแสงและสารละลายไม่สะท้อนแสงอย่าเลือกใช้หลอดสะท้อนแสง (ที่เกี่ยวข้องกับวัตถุคลาส) ไม่ใช่ว่า "ผิด" หรืออะไร แต่โดยทั่วไปแล้วสิ่งที่เกี่ยวข้องกับการสะท้อนนั้นไม่ชัดเจนและชัดเจนน้อยกว่า
ไม่มีความแตกต่างในพฤติกรรมที่ฉันสามารถค้นหาระหว่างทั้งสอง (นอกเหนือจากกรณีที่ชัดเจนเป็นโมฆะ) สำหรับเวอร์ชั่นที่ฉันชอบฉันจะเลือกรุ่นที่สอง มันเป็นวิธีมาตรฐานในการทำเช่นนี้ใน Java
หากมันทำให้ผู้อ่านสับสนกับรหัสของคุณ (เพราะString[] instanceof Object[]เป็นจริง) คุณอาจต้องการใช้คำสั่งแรกเพื่อให้ชัดเจนยิ่งขึ้นถ้าผู้ตรวจสอบโค้ดถามเกี่ยวกับมัน