มีอย่างเช่น instanceOf (Class <?> c) ​​ใน Java หรือไม่


88

ฉันต้องการตรวจสอบว่าวัตถุoเป็นอินสแตนซ์ของคลาสCหรือคลาสย่อยของC.

ตัวอย่างเช่นถ้าpเป็นของชั้นPointที่ฉันต้องการx.instanceOf(Point.class)ที่จะเป็นtrueและจะเป็นx.instanceOf(Object.class)true

ฉันต้องการให้มันใช้งานได้กับประเภทดั้งเดิมแบบบรรจุกล่อง ตัวอย่างเช่นถ้าxเป็นIntegerแล้วควรจะเป็นx.instanceOf(Integer.class)true

มีอย่างนั้นหรือ? ถ้าไม่ฉันจะใช้วิธีการดังกล่าวได้อย่างไร?


การจัดการชั้นเรียนแบบกล่องค่อนข้างยุ่ง
dfa

คำตอบ:


174

Class.isInstanceทำในสิ่งที่คุณต้องการ

if (Point.class.isInstance(someObj)){
    ...
}

แน่นอนคุณไม่ควรใช้หากสามารถใช้instanceofแทนได้ แต่สำหรับสถานการณ์สะท้อนมักมีประโยชน์


6
@ อาเหม็ดมันอาจจะช้ากว่า แต่สิ่งที่แย่กว่าคือมันยากที่จะเข้าใจ! หากมีวิธีง่ายๆในการทำบางสิ่งเช่นif (a instanceof Point)- แต่คุณทำด้วยวิธีที่ซับซ้อนกว่านี้ใครก็ตามที่อ่านโค้ดจะต้องคิดว่า "โอ้ต้องมีเหตุผลที่ทำให้สิ่งนี้ทำได้ยาก" และ จากนั้นข้ามไปที่เอกสารเพื่อดูว่าClass.isInstanceแตกต่างกันinstanceofอย่างไร คุณเสียเวลาเพื่อนร่วมงาน
gustafc

21

ฉันต้องการตรวจสอบว่าออบเจ็กต์ o เป็นอินสแตนซ์ของคลาส c หรือคลาสย่อยของ c หรือไม่ ตัวอย่างเช่นถ้า p เป็นคลาส Point ฉันต้องการ x.instanceOf (Point.class)

อืม ... อะไรนะ? o, p และ x คืออะไร?

ฉันต้องการให้มันทำงานกับประเภทดั้งเดิมด้วย ตัวอย่างเช่นถ้า x เป็นจำนวนเต็มแล้ว x.instanceOf (Integer.class) และ x.instanceOf (Object.class) ก็ควรเป็นจริง

ไม่ไม่ควรคอมไพล์ด้วยซ้ำ Primitives ไม่ใช่วัตถุและคุณไม่สามารถเรียกใช้เมธอดได้

อย่างไรก็ตามมีสามสิ่งซึ่งหนึ่งในนั้นสามารถบรรลุสิ่งที่คุณต้องการได้อย่างแน่นอน (แตกต่างกันบ้างตรงที่ใช้:

  • ตัวinstanceofดำเนินการถ้าคุณรู้จักคลาสในเวลาคอมไพล์
  • Class.isInstance ()หากคุณต้องการตรวจสอบคลาสของอ็อบเจ็กต์เทียบกับคลาสที่ไม่รู้จักในเวลาคอมไพล์
  • Class.isAssignableFrom ()ถ้าคุณต้องการตรวจสอบความสามารถในการกำหนดที่ได้รับจากวัตถุคลาสสองชิ้น

9
x instanceof Integer
x instanceof Object

คุณต้องใช้ไวยากรณ์ที่ถูกต้อง

สำหรับประเภท primitve คุณต้องทำมันให้แตกต่างอย่างสิ้นเชิง เนื่องจากคุณไม่สามารถสร้างเมธอดสำหรับพวกเขาได้คุณจึงต้องมีคลาสที่เก็บเมธอดไว้ ดังนั้นแทนที่จะเป็น "x.instanceOf (Integer.Class)" คุณต้องเรียก "MyClassComparer.instanceOf (x, Integer.Class)" หรืออะไรทำนองนั้น สิ่งนี้สามารถทำได้อย่างง่ายดายด้วยวิธีการโอเวอร์โหลด แต่ฉันไม่เห็นกรณีที่ฟังก์ชันนั้นจะเป็นที่ต้องการเลย


4

ในความเป็นจริงใน Java มีตัวดำเนินการบูลีนที่เรียกว่าอินสแตนซ์ของซึ่งสามารถใช้เพื่อพิจารณาว่าอ็อบเจ็กต์เป็นอินสแตนซ์ของคลาสอินสแตนซ์คลาสย่อยหรืออินสแตนซ์ของคลาสที่ใช้อินเทอร์เฟซเฉพาะ

if(obj instanceof SomeClass) {
    // Do something
}

Java Tutorial มีตัวอย่างที่ดีของตัวดำเนินการนี้


1
คุณไม่สามารถใช้ instanceof กับประเภทดั้งเดิมได้
dfa

4
เขาสับสนประเภทดั้งเดิมกับวัตถุ โปรดอ่าน ... "ตัวอย่างเช่นถ้า x เป็นจำนวนเต็มดังนั้น x.instanceOf (Integer.class) และ x.instanceOf (Object.class) ก็ควรเป็นจริง" อัปยศที่คุณลงคะแนนคำตอบทั้งหมด
ผู้ชนะฮิวโก้

Seconding (sp) คำแนะนำในการใช้ Java Tutorial เป็นข้อมูลอ้างอิงที่ดีสำหรับการเรียนรู้ภาษา
luis.espinal

0

คุณทำได้:

if (foo instanceof classNameYouWantToCheck) 

คุณไม่สามารถใช้ instanceof กับประเภทดั้งเดิมได้
dfa

ชั้นเรียนเป็นเพียงการแสดงว่าเขาควรเขียนชื่อชั้นที่นั่น ฉันจะแก้ไข
fmsf

0

"ฉันต้องการให้มันใช้งานได้กับประเภทดั้งเดิมเช่นถ้า x เป็นจำนวนเต็มดังนั้น x.instanceOf (Integer.class) และ x.instanceOf (Object.class) ก็ควรเป็นจริงด้วย"

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

(Integer)5 instanceof Integer

แต่ประเด็นจะเป็นอย่างไร


0

ด้านขวามือของ Class.isAssignableFrom()คลาสย่อย

ดังนั้นสำหรับ Objects objและ superclassClass<?> superCls

superCls.isAssignableFrom( obj.getClass() )

และ

obj instanceof superCls)

เทียบเท่า


-2

ฉันคิดว่าคุณสับสนเกี่ยวกับอินสแตนซ์ของวัตถุดิบและวัตถุทั่วไป

obj instanceof Class
obj instanceof Class<?> // this is the one you want

2
คุณไม่สามารถใช้ generics ทางด้านขวามือของอินสแตนซ์ของตัวดำเนินการได้เนื่องจากการลบประเภท
Matthias

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