มีการตั้งค่าหรือความแตกต่างพฤติกรรมระหว่างการใช้:
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
ในขณะที่พ่นisArray
NullPointerException
นำไปใช้กับอาร์เรย์ดั้งเดิม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[]
เป็นจริง) คุณอาจต้องการใช้คำสั่งแรกเพื่อให้ชัดเจนยิ่งขึ้นถ้าผู้ตรวจสอบโค้ดถามเกี่ยวกับมัน