หากคลาสBและคลาสCขยายคลาสAและฉันมีอ็อบเจกต์ประเภทBหรือCฉันจะกำหนดประเภทที่เป็นอินสแตนซ์ได้อย่างไร
หากคลาสBและคลาสCขยายคลาสAและฉันมีอ็อบเจกต์ประเภทBหรือCฉันจะกำหนดประเภทที่เป็นอินสแตนซ์ได้อย่างไร
คำตอบ:
if (obj instanceof C) {
//your code
}
if(!(obj instanceof C))
code Child1 child1 ต่อไปนี้= new Child1 (); Parent1 parentChild = new Child2 (); Child2 child2 = new Child2 (); (child1 อินสแตนซ์ของ Parent1); (child1 อินสแตนซ์ของ Child1); (parentChild instanceof Child2); (parentChild instanceof Parent1); (parentChild instanceof Child1); code มันอาจชัดเจนเจตนาของอินสแตนซ์ของ
ใช้Object.getClass () ส่งคืนประเภทรันไทม์ของวัตถุ
มีการนำเสนอคำตอบที่ถูกต้องหลายคำ แต่ยังมีวิธีการเพิ่มเติม: Class.isAssignableFrom()และพยายามที่จะโยนวัตถุ (ซึ่งอาจส่งClassCastException)
ขอสรุปวิธีที่เป็นไปได้ในการทดสอบว่าวัตถุobjเป็นตัวอย่างของประเภทหรือไม่C:
// Method #1
if (obj instanceof C)
;
// Method #2
if (C.class.isInstance(obj))
;
// Method #3
if (C.class.isAssignableFrom(obj.getClass()))
;
// Method #4
try {
C c = (C) obj;
// No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}
// Method #5
try {
C c = C.class.cast(obj);
// No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}
nullการจัดการมีความแตกต่างในการnullจัดการว่า:
falseว่าถ้าobjเป็นnull( nullไม่ใช่ตัวอย่างของอะไร)NullPointerExceptionชัดขึ้นnullเพราะnullสามารถใช้กับทุกประเภท!ข้อควรจำ:
nullไม่ใช่ตัวอย่างทุกประเภท แต่สามารถส่งไปเป็นประเภทใดก็ได้
Class.getName()ไม่ควรใช้เพื่อทำการทดสอบ"is-instance-of"ถ้าวัตถุไม่ได้เป็นประเภทCแต่เป็นคลาสย่อยของมันมันอาจมีชื่อและแพคเกจที่แตกต่างกันโดยสิ้นเชิง (ดังนั้นชื่อคลาสจะไม่ตรงกัน) แต่เป็น Cยังคงเป็นประเภทClass.isAssignableFrom()ไม่สมมาตร : obj.getClass().isAssignableFrom(C.class)จะกลับมาfalseถ้าประเภทของการobjเป็น subclass Cของคุณสามารถใช้ได้:
Object instance = new SomeClass();
instance.getClass().getName(); //will return the name (as String) (== "SomeClass")
instance.getClass(); //will return the SomeClass' Class object
HTH แต่ฉันคิดว่าส่วนใหญ่แล้วมันก็ไม่ใช่วิธีปฏิบัติที่ดีที่จะใช้มันเพื่อควบคุมโฟลว์หรืออะไรทำนองนั้น ...
การใช้วิธีการใด ๆ ที่แนะนำถือว่าเป็นกลิ่นรหัสซึ่งมีพื้นฐานมาจากการออกแบบ OO ที่ไม่ดี
หากการออกแบบของคุณเป็นสิ่งที่ดีที่คุณไม่ควรพบว่าตัวเองจำเป็นต้องใช้หรือgetClass()instanceof
วิธีการใด ๆ ที่แนะนำจะทำ แต่เพียงสิ่งที่ควรคำนึงถึงการออกแบบที่ชาญฉลาด
เราสามารถใช้การสะท้อนในกรณีนี้
objectName.getClass().getName();
ตัวอย่าง:-
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getClass().getName();
}
ในกรณีนี้คุณจะได้รับชื่อของคลาสที่อ็อบเจกต์ส่งผ่านไปยังHttpServletRequestตัวแปรผู้อ้างอิงของอินเทอร์เฟซ
obj.getClass()จะส่งกลับ className นำหน้าด้วยคำว่าclass
request.getClass().getName();พิมพ์แพ็คเกจทั้งหมด! พร้อมกับชื่อคลาส
นอกจากนี้ยังมี.isInstanceวิธีการในClassคลาส "" ถ้าคุณได้คลาสของวัตถุผ่านmyBanana.getClass()คุณสามารถดูว่าวัตถุของคุณmyAppleเป็นอินสแตนซ์ของคลาสเดียวกันกับmyBananaผ่านหรือไม่
myBanana.getClass().isInstance(myApple)
การตรวจสอบด้วยisinstance()จะไม่เพียงพอหากคุณต้องการทราบในเวลาทำงาน ใช้:
if(someObject.getClass().equals(C.class){
// do something
}
ฉันใช้ฟังก์ชั่นการเป่าในคลาส GeneralUtils ของฉันตรวจสอบว่าอาจมีประโยชน์
public String getFieldType(Object o) {
if (o == null) {
return "Unable to identify the class name";
}
return o.getClass().getName();
}
ฉันใช้ Java 8 generics เพื่อรับอินสแตนซ์ของวัตถุที่ runtime แทนที่จะต้องใช้ตัวพิมพ์สลับ
public <T> void print(T data) {
System.out.println(data.getClass().getName()+" => The data is " + data);
}
ผ่านประเภทข้อมูลใด ๆ และวิธีการจะพิมพ์ประเภทของข้อมูลที่คุณส่งผ่านในขณะที่เรียกมัน เช่น
String str = "Hello World";
int number = 10;
double decimal = 10.0;
float f = 10F;
long l = 10L;
List list = new ArrayList();
print(str);
print(number);
print(decimal);
print(f);
print(l);
print(list);
ต่อไปนี้เป็นผลลัพธ์
java.lang.String => The data is Hello World
java.lang.Integer => The data is 10
java.lang.Double => The data is 10.0
java.lang.Float => The data is 10.0
java.lang.Long => The data is 10
java.util.ArrayList => The data is []