ทำไมโค้ดนี้ไม่คอมไพล์
public boolean isOf(Class clazz, Object obj){
if(obj instanceof clazz){
return true;
}else{
return false;
}
}
ทำไมฉันจึงไม่สามารถส่งผ่านตัวแปรระดับเพื่อinstanceof
?
ทำไมโค้ดนี้ไม่คอมไพล์
public boolean isOf(Class clazz, Object obj){
if(obj instanceof clazz){
return true;
}else{
return false;
}
}
ทำไมฉันจึงไม่สามารถส่งผ่านตัวแปรระดับเพื่อinstanceof
?
คำตอบ:
instanceof
ประกอบการทำงานในประเภทของการอ้างอิงเช่นและไม่เกี่ยวกับวัตถุเช่นInteger
new Integer(213)
คุณอาจต้องการบางอย่างเช่น
clazz.isInstance(obj)
หมายเหตุด้านข้าง: โค้ดของคุณจะกระชับมากขึ้นหากคุณเขียน
public boolean isOf(Class clazz, Object obj){
return clazz.isInstance(obj)
}
ไม่แน่ใจจริงๆว่าคุณต้องการวิธีการอีกต่อไปหรือไม่
Integer
คือไม่ได้ตัวอักษรระดับ Integer.class
จะเป็นคลาสลิเทอรัล (ดู§ 15.8.2 ของ JLS: java.sun.com/docs/books/jls/third_edition/html/… ) ตัวinstanceof
ดำเนินการใช้ "ReferenceType" (aka a type name) ตามที่ระบุ§ 15.20.2 ของ JLS: java.sun.com/docs/books/jls/third_edition/html/…
clazz.isInstance(obj)
ตั้งแต่มีการจัดหาวัตถุมาแล้ว
instanceof
สามารถใช้ได้เฉพาะกับชื่อคลาสที่ชัดเจนเท่านั้น (ระบุในเวลาคอมไพล์) ในการตรวจสอบรันไทม์คุณควรทำ:
clazz.isInstance(obj)
สิ่งนี้มีข้อได้เปรียบเล็กน้อยclazz.isAssignableFrom(..)
เนื่องจากเกี่ยวข้องกับเคสที่obj == null
ดีกว่า
เป็นคนอื่นได้กล่าวถึงคุณจะไม่สามารถส่งผ่านตัวแปรระดับให้instanceof
เพราะอ้างอิงตัวแปรระดับอินสแตนซ์ของวัตถุในขณะที่ด้านขวามือของinstanceof
จะต้องมีประเภท นั่นคือinstanceof
ไม่ได้หมายความว่า "y คืออินสแตนซ์ของ Object x" แต่หมายถึง "y คืออินสแตนซ์ของประเภท X" ในกรณีที่คุณไม่ทราบความแตกต่างระหว่างวัตถุและประเภทให้พิจารณา:
Object o = new Object();
นี่คือประเภทObject
และo
เป็นการอ้างอิงถึงอินสแตนซ์ของ Object ที่มีประเภทนั้น ดังนั้น:
if(o instanceof Object)
ถูกต้อง แต่
if(o instanceof o)
ไม่ใช่เพราะo
ทางด้านขวามือเป็น Object ไม่ใช่ประเภท
เฉพาะเจาะจงมากขึ้นสำหรับกรณีของคุณอินสแตนซ์คลาสไม่ใช่ประเภท แต่เป็นObject (ซึ่ง JVM สร้างขึ้นสำหรับคุณ) ในวิธีการของคุณClass
เป็นประเภท แต่clazz
เป็นวัตถุ (เช่นกันการอ้างอิงถึงวัตถุ)
สิ่งที่คุณต้องการคือวิธีเปรียบเทียบ Object กับ Class Object isInstance()
แต่กลับกลายเป็นว่านี้จึงเป็นที่นิยมนี้จะให้คุณเป็นวิธีการของวัตถุคลาส:
นี่คือ Java Doc สำหรับ isInstance ซึ่งอธิบายสิ่งนี้ได้ดีกว่า:
public boolean isInstance(Object obj)
พิจารณาว่าอ็อบเจ็กต์ที่ระบุเข้ากันได้กับการกำหนดหรือไม่กับอ็อบเจ็กต์ที่แสดงโดยคลาสนี้ วิธีนี้เทียบเท่าไดนามิกของตัวดำเนินการอินสแตนซ์ภาษา Java เมธอดจะคืนค่าเป็นจริงหากอาร์กิวเมนต์ Object ที่ระบุไม่เป็นค่าว่างและสามารถส่งไปยังประเภทการอ้างอิงที่แสดงโดยอ็อบเจ็กต์คลาสนี้โดยไม่ต้องเพิ่ม ClassCastException มันจะส่งกลับเท็จเป็นอย่างอื่น
โดยเฉพาะอย่างยิ่งถ้าคลาสอ็อบเจ็กต์นี้แสดงถึงคลาสที่ประกาศไว้เมธอดนี้จะคืนค่า true หากอาร์กิวเมนต์ Object ที่ระบุเป็นอินสแตนซ์ของคลาสที่เป็นตัวแทน (หรือคลาสย่อยใด ๆ ) มันจะส่งกลับเท็จเป็นอย่างอื่น ถ้าคลาสออบเจ็กต์นี้แสดงถึงคลาสอาร์เรย์เมธอดนี้จะคืนค่าจริงหากอาร์กิวเมนต์ Object ที่ระบุสามารถถูกแปลงเป็นอ็อบเจ็กต์ของคลาสอาร์เรย์โดยการแปลงข้อมูลประจำตัวหรือโดยการแปลงการอ้างอิงที่กว้างขึ้น มันจะส่งกลับเท็จเป็นอย่างอื่น ถ้าคลาสอ็อบเจ็กต์นี้แสดงถึงอินเทอร์เฟซเมธอดนี้จะคืนค่า true ถ้าคลาสหรือซูเปอร์คลาสใด ๆ ของอาร์กิวเมนต์อ็อบเจ็กต์ที่ระบุใช้อินเทอร์เฟซนี้ มันจะส่งกลับเท็จเป็นอย่างอื่น ถ้าคลาสอ็อบเจ็กต์นี้แสดงถึงชนิดดั้งเดิมเมธอดนี้จะส่งคืนเท็จ
พารามิเตอร์: obj - อ็อบเจ็กต์ที่จะตรวจสอบ
Returns: true ถ้า obj เป็นอินสแตนซ์ของคลาสนี้
ตั้งแต่: JDK1.1
ประการแรกinstanceof
ต้องว่าถูกดำเนินการทางด้านขวาเป็นระดับที่เกิดขึ้นจริง (เช่นobj instanceof Object
หรือobj instanceof Integer
) Class
และไม่ใช่ตัวแปรประเภท ประการที่สองคุณได้ทำผิดพลาดสำหรับมือใหม่ซึ่งคุณไม่ควรทำจริงๆ ... รูปแบบต่อไปนี้:
ถ้า ( conditional_expression ) { กลับจริง; } else { กลับเท็จ }
ข้างต้นสามารถ refactored เป็น:
ส่งคืนconditional_expression ;
คุณควรทำการ refactoring นั้นเสมอเนื่องจากจะช่วยลดคำสั่ง if ... else ที่ซ้ำซ้อน ในทำนองเดียวกันนิพจน์สามารถปรับเปลี่ยนให้ได้ผลลัพธ์เดียวกันreturn conditional_expression ? true : false;