เหตุใดจึงไม่สามารถส่งผ่านตัวแปร“ Class” ไปยัง instanceof ได้


89

ทำไมโค้ดนี้ไม่คอมไพล์

    public boolean isOf(Class clazz, Object obj){
        if(obj instanceof clazz){
            return true;
        }else{
            return false;
        }
    }

ทำไมฉันจึงไม่สามารถส่งผ่านตัวแปรระดับเพื่อinstanceof?

คำตอบ:


131

instanceofประกอบการทำงานในประเภทของการอ้างอิงเช่นและไม่เกี่ยวกับวัตถุเช่นInteger new Integer(213)คุณอาจต้องการบางอย่างเช่น

clazz.isInstance(obj)

หมายเหตุด้านข้าง: โค้ดของคุณจะกระชับมากขึ้นหากคุณเขียน

public boolean isOf(Class clazz, Object obj){
    return clazz.isInstance(obj)
}

ไม่แน่ใจจริงๆว่าคุณต้องการวิธีการอีกต่อไปหรือไม่


ฉันรู้ว่ารหัสนั้นไร้ประโยชน์ฉันแค่อยากจะแสดงให้เห็นถึงความสับสนของฉัน :)
eric2323223

6
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/…
Joachim Sauer

3
ฉันจะใช้clazz.isInstance(obj)ตั้งแต่มีการจัดหาวัตถุมาแล้ว
Donal Fellows

13

instanceofสามารถใช้ได้เฉพาะกับชื่อคลาสที่ชัดเจนเท่านั้น (ระบุในเวลาคอมไพล์) ในการตรวจสอบรันไทม์คุณควรทำ:

clazz.isInstance(obj)

สิ่งนี้มีข้อได้เปรียบเล็กน้อยclazz.isAssignableFrom(..)เนื่องจากเกี่ยวข้องกับเคสที่obj == nullดีกว่า


5

เป็นคนอื่นได้กล่าวถึงคุณจะไม่สามารถส่งผ่านตัวแปรระดับให้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


3

ประการแรกinstanceofต้องว่าถูกดำเนินการทางด้านขวาเป็นระดับที่เกิดขึ้นจริง (เช่นobj instanceof Objectหรือobj instanceof Integer) Classและไม่ใช่ตัวแปรประเภท ประการที่สองคุณได้ทำผิดพลาดสำหรับมือใหม่ซึ่งคุณไม่ควรทำจริงๆ ... รูปแบบต่อไปนี้:

ถ้า ( conditional_expression ) {
    กลับจริง;
} else {
    กลับเท็จ
}

ข้างต้นสามารถ refactored เป็น:

ส่งคืนconditional_expression ;

คุณควรทำการ refactoring นั้นเสมอเนื่องจากจะช่วยลดคำสั่ง if ... else ที่ซ้ำซ้อน ในทำนองเดียวกันนิพจน์สามารถปรับเปลี่ยนให้ได้ผลลัพธ์เดียวกันreturn conditional_expression ? true : false;


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