อะไรคือความแตกต่างระหว่างอินสแตนซ์ของและ Class.isAssignableFrom (…)?


458

ข้อใดต่อไปนี้ดีกว่า

a instanceof B

หรือ

B.class.isAssignableFrom(a.getClass())

ความแตกต่างเพียงอย่างเดียวที่ฉันรู้คือเมื่อ 'a' เป็นโมฆะอันแรกจะคืนค่าเท็จในขณะที่ตัวที่สองส่งข้อยกเว้น นอกจากนั้นพวกเขาจะให้ผลลัพธ์เดียวกันเสมอหรือไม่?


17
สำหรับเร็กคอร์ด isInstance () เป็นวิธีที่สะดวกที่สุดในการตรวจสอบว่าสามารถนำวัตถุออกเป็นประเภทคลาสได้หรือไม่ (ดูรายละเอียดเพิ่มเติมได้ที่: tshikatshikaaa.blogspot.nl/2012/07/ ...... )
Jérôme Verstrynge

คำตอบ:


498

เมื่อใช้instanceofคุณจำเป็นต้องรู้ระดับของBเวลารวบรวม เมื่อใช้isAssignableFrom()มันสามารถเป็นแบบไดนามิกและเปลี่ยนแปลงระหว่างรันไทม์


12
ฉันไม่ได้รับมัน - โปรดละเอียดในเหตุผลที่a instanceof Bref.getClass()เราไม่สามารถเขียน นี่เป็นคำตอบที่ได้รับการยอมรับได้อย่างไรพร้อมคำอธิบายเล็กน้อย (หรือคำขาด)
Eliran Malka

65
ไวยากรณ์ไม่a instanceof Bref a instanceof Bref.classอาร์กิวเมนต์ที่สองของตัวดำเนินการ instanceof คือชื่อคลาสไม่ใช่นิพจน์ที่แก้ไขเป็นอินสแตนซ์อ็อบเจ็กต์คลาส
Brandon Bloom

2
ใช่ "ไดนามิก" ไปโดยไม่บอก :) นอกเหนือจากประสิทธิภาพแล้วนี่คือความแตกต่างที่แท้จริง
peterk

2
@EliranMalka บางทีคุณอาจมีคลาสที่สร้างขึ้นในขณะใช้งานจริง เช่นเดียวกับวัตถุพร็อกซี่
Wagner Tsuchiya

ดังนั้นในB.class.isAssignableFrom(a.getClass())B จึงเป็นที่รู้จักและa instanceof Bดีกว่า ขวา?
Florian F

208

instanceofสามารถใช้ได้กับประเภทการอ้างอิงเท่านั้นไม่ใช่แบบดั้งเดิม isAssignableFrom()สามารถใช้กับวัตถุคลาสใด ๆ :

a instanceof int  // syntax error
3 instanceof Foo  // syntax error
int.class.isAssignableFrom(int.class)  // true

ดู http://java.sun.com/javase/6/docs/api/java/lang/Class.html#isAssignableFrom(java.lang.Class)


10
ฉันไม่เห็นจุดใช้อินสแตนซ์ของ / isAssignableFrom กับประเภทดั้งเดิม
จิมมี่ต.

116

การพูดคุยในแง่ของประสิทธิภาพ:

TL; DR

ใช้isInstanceหรือinstanceofที่มีประสิทธิภาพใกล้เคียงกัน isAssignable จากช้ากว่าเล็กน้อย

จัดเรียงตามประสิทธิภาพ:

  1. isinstance
  2. instanceof (+ 0.5%)
  3. isAssignableFrom (+ 2.7%)

อ้างอิงตามเกณฑ์มาตรฐานของการวนซ้ำ 2,000 รอบบน JAVA 8 Windows x64 พร้อมการวอร์มอัพซ้ำ 20 ครั้ง

ในทางทฤษฎี

การใช้เครื่องมือดูไบเทคโคเดอร์อ่อน ๆ ทำให้เราสามารถแปลโอเปอเรเตอร์แต่ละตัวเป็น bytecode

ในบริบทของ:

package foo;

public class Benchmark
{
  public static final Object a = new A();
  public static final Object b = new B();

  ...

}

JAVA:

b instanceof A;

bytecode:

getstatic foo/Benchmark.b:java.lang.Object
instanceof foo/A

JAVA:

A.class.isInstance(b);

bytecode:

ldc Lfoo/A; (org.objectweb.asm.Type)
getstatic foo/Benchmark.b:java.lang.Object
invokevirtual java/lang/Class isInstance((Ljava/lang/Object;)Z);

JAVA:

A.class.isAssignableFrom(b.getClass());

bytecode:

ldc Lfoo/A; (org.objectweb.asm.Type)
getstatic foo/Benchmark.b:java.lang.Object
invokevirtual java/lang/Object getClass(()Ljava/lang/Class;);
invokevirtual java/lang/Class isAssignableFrom((Ljava/lang/Class;)Z);

การวัดจำนวนคำสั่ง bytecode ที่ใช้โดยผู้ให้บริการแต่ละรายเราสามารถคาดหวังอินสแตนซ์ของและisInstanceให้เร็วกว่าisAssableableจาก อย่างไรก็ตามประสิทธิภาพที่แท้จริงไม่ได้ถูกกำหนดโดย bytecode แต่ตามรหัสเครื่อง (ซึ่งขึ้นอยู่กับแพลตฟอร์ม) ลองทำเกณฑ์มาตรฐานขนาดเล็กสำหรับผู้ให้บริการแต่ละราย

เกณฑ์มาตรฐาน

เครดิต: ตามที่ได้รับคำแนะนำจาก @ aleksandr-dubinsky และขอบคุณ @yura ที่ให้รหัสพื้นฐานนี่คือเกณฑ์มาตรฐานของJMH (ดูคู่มือการปรับแต่งนี้):

class A {}
class B extends A {}

public class Benchmark {

    public static final Object a = new A();
    public static final Object b = new B();

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public boolean testInstanceOf()
    {
        return b instanceof A;
    }

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public boolean testIsInstance()
    {
        return A.class.isInstance(b);
    }

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public boolean testIsAssignableFrom()
    {
        return A.class.isAssignableFrom(b.getClass());
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(TestPerf2.class.getSimpleName())
                .warmupIterations(20)
                .measurementIterations(2000)
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}

ให้ผลลัพธ์ดังต่อไปนี้ (คะแนนคือจำนวนการปฏิบัติงานในหน่วยเวลาดังนั้นยิ่งคะแนนดีขึ้นเท่าใด):

Benchmark                       Mode   Cnt    Score   Error   Units
Benchmark.testIsInstance        thrpt  2000  373,061 ± 0,115  ops/us
Benchmark.testInstanceOf        thrpt  2000  371,047 ± 0,131  ops/us
Benchmark.testIsAssignableFrom  thrpt  2000  363,648 ± 0,289  ops/us

คำเตือน

  • มาตรฐานคือ JVM และขึ้นอยู่กับแพลตฟอร์ม เนื่องจากไม่มีความแตกต่างอย่างมีนัยสำคัญระหว่างการดำเนินการแต่ละอย่างดังนั้นจึงอาจเป็นไปได้ที่จะได้รับผลลัพธ์ที่แตกต่างกัน (และอาจแตกต่างกันออกไป!) ในเวอร์ชัน JAVA และ / หรือแพลตฟอร์มอื่นเช่น Solaris, Mac หรือ Linux
  • มาตรฐานเปรียบเทียบประสิทธิภาพของ "is B เป็นตัวอย่างของ A" เมื่อ "B ขยาย A" โดยตรง หากลำดับชั้นของชั้นลึกและซับซ้อนมากขึ้น (เช่น B ขยาย X ซึ่งขยาย Y ซึ่งขยาย Z ซึ่งขยาย A) ผลลัพธ์อาจแตกต่างกัน
  • ขอแนะนำให้เขียนรหัสก่อนเลือกหนึ่งในตัวดำเนินการ (สะดวกที่สุด) จากนั้นโปรไฟล์รหัสของคุณเพื่อตรวจสอบว่ามีปัญหาคอขวดหรือไม่ บางทีโอเปอเรเตอร์นี้เล็กน้อยในบริบทของรหัสของคุณหรืออาจ ...
  • เกี่ยวกับจุดก่อนหน้าinstanceofในบริบทของรหัสของคุณอาจได้รับการปรับให้ง่ายกว่าisInstanceตัวอย่างเช่น ...

ในการให้ตัวอย่างให้ใช้ลูปต่อไปนี้:

class A{}
class B extends A{}

A b = new B();

boolean execute(){
  return A.class.isAssignableFrom(b.getClass());
  // return A.class.isInstance(b);
  // return b instanceof A;
}

// Warmup the code
for (int i = 0; i < 100; ++i)
  execute();

// Time it
int count = 100000;
final long start = System.nanoTime();
for(int i=0; i<count; i++){
   execute();
}
final long elapsed = System.nanoTime() - start;

ต้องขอบคุณ JIT รหัสนี้จึงได้รับการปรับปรุงและเราจะได้รับ:

  • อินสแตนซ์ของ: 6ms
  • isInstance: 12ms
  • isAssignable จาก: 15ms

บันทึก

แต่เดิมโพสต์นี้กำลังสร้างมาตรฐานของตัวเองโดยใช้for for loop ใน JAVA ดิบซึ่งให้ผลลัพธ์ที่ไม่น่าเชื่อถือเนื่องจากการเพิ่มประสิทธิภาพบางอย่างเช่น Just In Time สามารถกำจัดลูปได้ ดังนั้นจึงเป็นการวัดว่าคอมไพเลอร์ JIT ใช้เวลานานแค่ไหนในการปรับลูปให้เหมาะสม: ดูการทดสอบประสิทธิภาพโดยไม่ขึ้นกับจำนวนการวนซ้ำสำหรับรายละเอียดเพิ่มเติม

คำถามที่เกี่ยวข้อง


6
ใช่instanceofเป็นไบต์ที่ใช้ตรรกะเดียวกันเป็นหลักcheckcast(bytecode ที่อยู่เบื้องหลังการคัดเลือก) มันจะเร็วกว่าตัวเลือกอื่นโดยไม่คำนึงถึงระดับของการเพิ่มประสิทธิภาพ JITC
Licks ร้อน

1
ซึ่งเหมาะสมตามที่เป็นisAssignableFrom()อยู่แบบไดนามิก
Matthieu

ใช่ด้วยผลลัพธ์ของ JMH นั้นแตกต่างกันอย่างสิ้นเชิง
Yura

สวัสดีเกณฑ์มาตรฐานที่ดีเพียงพบกับสถานการณ์ที่ isAignignFrom ถูกเรียกหลายพันครั้งเปลี่ยนเป็นอินสแตนซ์ของสร้างความแตกต่างอย่างแท้จริง การตอบกลับนี้จะคุ้มค่ากับการโพสต์บล็อกที่ไหนสักแห่ง ... ;)
Martin

33

เทียบเท่าโดยตรงกับa instanceof Bคือ

B.class.isInstance(a)

วิธีนี้ใช้งานได้ (คืนค่าเท็จ) เมื่อaเป็นnullเช่นกัน


เยี่ยม แต่นี่ไม่ได้ตอบคำถามและควรเป็นความคิดเห็น
Madbreaks

23

นอกเหนือจากความแตกต่างพื้นฐานดังกล่าวข้างต้นมีความแตกต่างที่สำคัญหลักระหว่างผู้ประกอบการของอินสแตนซ์และวิธี isAssignableFrom ในชั้นเรียน

อ่านinstanceofว่า“ นี่คือ (ส่วนซ้าย) ตัวอย่างของคลาสนี้หรือคลาสย่อยของส่วนนี้ (ส่วนที่เหมาะสม)” และอ่านx.getClass().isAssignableFrom(Y.class)เป็น“ ฉันจะเขียนX x = new Y()” ได้อย่างไร ในคำอื่น ๆ ผู้ประกอบการ instanceof ตรวจสอบว่าวัตถุซ้ายเหมือนกันหรือคลาสย่อยของคลาสที่เหมาะสมในขณะที่isAssignableFromตรวจสอบว่าเราสามารถกำหนดวัตถุของคลาสพารามิเตอร์ (จาก) เพื่อการอ้างอิงของระดับที่วิธีการที่เรียกว่า
โปรดทราบว่าทั้งสองนี้พิจารณาอินสแตนซ์จริงไม่ใช่ประเภทการอ้างอิง

ลองพิจารณาตัวอย่างของ 3 คลาส A, B และ C โดยที่ C ขยาย B และ B ขยาย A

B b = new C();

System.out.println(b instanceof A); //is b (which is actually class C object) instance of A, yes. This will return true.  
System.out.println(b instanceof B); // is b (which is actually class C object) instance of B, yes. This will return true.  
System.out.println(b instanceof C); // is b (which is actually class C object) instance of C, yes. This will return true. If the first statement would be B b = new B(), this would have been false.
System.out.println(b.getClass().isAssignableFrom(A.class));//Can I write C c = new A(), no. So this is false.
System.out.println(b.getClass().isAssignableFrom(B.class)); //Can I write C c = new B(), no. So this is false.
System.out.println(b.getClass().isAssignableFrom(C.class)); //Can I write C c = new C(), Yes. So this is true.

3
b instanceof Aเทียบเท่ากับA.class.isAssignableFrom(b.getClass())(ตามที่ OP สังเกตเห็น) ตัวอย่างของคุณถูกต้อง แต่ไม่เกี่ยวข้อง
Karu

เนื่องจากnew Y()อาจไม่ถูกกฎหมายหากYเป็นนามธรรมหรือไม่มีตัวสร้างค่าเริ่มต้นสาธารณะคุณสามารถพูดได้ว่าX x = (Y)nullถูกต้องตามกฎหมายถ้าหากx.getClass().isAssignableFrom(Y.class)เป็นจริง
Earth Engine

2
ทำไม 'b.getClass (). isAssignableFrom (A.class)' ในตัวอย่างนี้ ฉันเดาว่าตัวอย่างควรเป็นแบบย้อนกลับ A.class.isAssignableFrom (b.getClass ())
loshad vtapkah

14

นอกจากนี้ยังมีข้อแตกต่างอื่น ๆ :

อินสแตนซ์ที่ว่างของ X falseไม่สำคัญว่า X คืออะไร

null.getClass () isAssignableFrom (X) จะโยน NullPointerException


4
-1 ไม่ถูกต้อง: null instanceof X(โดยที่ X เป็นชั้นบางที่รู้จักกันที่รวบรวมเวลา) falseมักจะกลับมา
Caspar

4
@ คาสปาในขณะที่คุณถูกต้องความคิดพื้นฐานเป็นจุดที่ดี ฉันแก้ไขโพสต์เพื่อให้ถูกต้อง
erickson

1
สิ่งนี้มีประโยชน์กรณีขอบมีความสำคัญเสมอ :)
ล้านล้าน

เพื่อให้เทียบเท่ากับบรรทัดแรกบรรทัดที่สองควรเป็นX.class.isAssignableFrom(null.getClass())อย่างไร แต่ใช่การเรียกgetClass()อ้างอิงแบบ null จะส่งผลให้เกิด NPE
William Price

คำตอบนี้พลาดจุด - การอ้างอิงเป็นโมฆะไม่เกี่ยวข้องเนื่องจากความล้มเหลวเกิดขึ้นนอกการดำเนินการ (คุณจำเป็นต้องตรวจสอบ null ก่อนที่จะใช้การอ้างอิงเช่นนั้นเสมอ) โดยทั่วไปgetClass()ไม่ควรใช้กับisAssignableFromในตอนแรก - การดำเนินการมีความหมายสำหรับสถานการณ์ที่ไม่มีวัตถุ หากคุณมีการอ้างอิงวัตถุaใช้a instanceof SomeClass(ถ้าคุณทำทราบชนิดSomeClass) หรือsomeObject.getClass().isInstance(a)(ถ้าคุณไม่ทราบชนิดของsomeObject)
AndrewF

12

ยังมีความแตกต่างอื่น หากประเภท (Class) ที่จะทดสอบเป็นแบบไดนามิกเช่นส่งผ่านเป็นพารามิเตอร์ method ดังนั้น instanceof จะไม่ตัดให้คุณ

boolean test(Class clazz) {
   return (this instanceof clazz); // clazz cannot be resolved to a type.
}

แต่คุณสามารถทำได้:

boolean test(Class clazz) {
   return (clazz.isAssignableFrom(this.getClass())); // okidoki
}

โอ๊ะฉันเห็นคำตอบนี้ครอบคลุมแล้ว บางทีตัวอย่างนี้อาจมีประโยชน์กับบางคน


3
จริง ๆ แล้วไม่มีคำตอบที่ถูกต้องจริงๆ isAssignable จากการทำงานกับคลาส, Class.isInstance เป็นอะนาล็อกของ'instanceof'
bestsss

ในการใส่ความคิดเห็นที่ถูกต้องของ @ bestsss ลงในโค้ดที่เป็นรูปธรรม: เนื่องจากคุณมีวัตถุ ( this) clazz.isInstance(this)จะดีกว่าในตัวอย่างของคุณ
AndrewF

7

หัวข้อนี้ให้ฉันเข้าใจว่าinstanceofแตกต่างจากisAssignableFromดังนั้นฉันคิดว่าฉันจะแบ่งปันบางอย่างของตัวเอง

ฉันได้พบว่าการใช้ isAssignableFromเป็นวิธีเดียว (อาจไม่ใช่วิธีเดียว แต่อาจเป็นวิธีที่ง่ายที่สุด) ในการถามตนเองว่าการอ้างอิงของคลาสหนึ่งสามารถใช้อินสแตนซ์ของคลาสอื่นได้หรือไม่เมื่อมีอินสแตนซ์ของคลาสที่ไม่ทำการเปรียบเทียบ

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


5

instanceof ไม่สามารถใช้กับชนิดดั้งเดิมหรือประเภททั่วไปอย่างใดอย่างหนึ่ง ในรหัสต่อไปนี้:

//Define Class< T > type ... 

Object e = new Object();

if(e instanceof T) {
  // Do something.
}

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

ไม่รวบรวมเนื่องจากการลบประเภทลบการอ้างอิงรันไทม์ อย่างไรก็ตามรหัสด้านล่างจะรวบรวม:

if( type.isAssignableFrom(e.getClass())){
  // Do something.
}

4

พิจารณาสถานการณ์ต่อไปนี้ สมมติว่าคุณต้องการตรวจสอบว่า Type A เป็น class super ของประเภท obj หรือไม่คุณสามารถไปได้

... A.class.isAssignableFrom (obj.getClass ()) ...

หรือ

... obj instanceof A ...

แต่โซลูชัน isAssignableFrom ต้องการให้ชนิดของ obj สามารถมองเห็นได้ที่นี่ หากนี่ไม่ใช่กรณี (เช่นชนิดของ obj อาจเป็นคลาสส่วนตัวภายใน) ตัวเลือกนี้จะไม่ทำงาน อย่างไรก็ตามการแก้ปัญหาอินสแตนซ์ของจะทำงานเสมอ


2
นั่นไม่เป็นความจริง โปรดดู "Adam Rosenfield" ความคิดเห็นstackoverflow.com/questions/496928/…
Maxim Veksler

1
คุณช่วยอธิบาย "นั่นไม่จริง" ได้ไหม? ความคิดเห็นที่คุณอ้างถึงไม่มีส่วนเกี่ยวข้องกับสถานการณ์ในโพสต์ของฉัน ฉันมีรหัสทดสอบบางอย่างที่สำรองคำอธิบายไว้
พีชคณิต

หากคุณมีการอ้างอิงที่ไม่เป็นโมฆะไปยังอินสแตนซ์ของวัตถุ ( objในตัวอย่างนี้) ชนิดใด ๆจากนั้นคุณสามารถเรียกgetClass()วิธีการสาธารณะที่จะได้รับเมตาดาต้าสะท้อนสำหรับการใช้งานคลาส สิ่งนี้เป็นจริงแม้ว่าการใช้ประเภทชั้นเรียนจะไม่สามารถมองเห็นได้ตามกฎหมาย ณ สถานที่นั้นในเวลารวบรวม ไม่เป็นไรตอนรันไทม์เพราะสำหรับคุณที่จะเก็บการobjอ้างอิงบางเส้นทางรหัสที่ในที่สุดก็มีการเข้าถึงทางกฎหมายในชั้นเรียนที่สร้างขึ้นหนึ่งและให้ (รั่วไหลออกมา) ให้คุณ
วิลเลียมราคา

0
isAssignableFrom(A, B) =

if (A == B) return true
else if (B == java.lang.Object) return false
else return isAssignableFrom(A, getSuperClass(B))

โค้ดหลอกข้างต้นเป็นคำจำกัดความของหากการอ้างอิงประเภท / คลาส A สามารถกำหนดได้จากการอ้างอิงประเภท / คลาส B มันเป็นนิยามแบบเรียกซ้ำ สำหรับบางคนอาจมีประโยชน์สำหรับบางคนอาจทำให้เกิดความสับสน ฉันจะเพิ่มในกรณีที่ใครบางคนควรพบว่ามีประโยชน์ นี่เป็นเพียงความพยายามในการจับความเข้าใจของฉันไม่ใช่คำจำกัดความอย่างเป็นทางการ มันถูกใช้ในการติดตั้ง Java VM บางอย่างและทำงานกับโปรแกรมตัวอย่างจำนวนมากดังนั้นในขณะที่ฉันไม่สามารถรับประกันได้ว่าจะจับภาพทุกด้านของ isAssignable จากมันไม่ได้ปิดอย่างสมบูรณ์


2
โปรดอธิบายว่ารหัสนี้ทำงานอะไรและตอบคำถามอย่างไร
คดีของกองทุนโมนิกา

0

การพูดคุยในแง่ของประสิทธิภาพ "2" (กับ JMH):

class A{}
class B extends A{}

public class InstanceOfTest {

public static final Object a = new A();
public static final Object b = new B();

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public boolean testInstanceOf()
{
    return b instanceof A;
}

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public boolean testIsInstance()
{
    return A.class.isInstance(b);
}

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public boolean testIsAssignableFrom()
{
    return A.class.isAssignableFrom(b.getClass());
}

public static void main(String[] args) throws RunnerException {
    Options opt = new OptionsBuilder()
            .include(InstanceOfTest.class.getSimpleName())
            .warmupIterations(5)
            .measurementIterations(5)
            .forks(1)
            .build();

    new Runner(opt).run();
}
}

มันให้:

Benchmark                            Mode  Cnt  Score   Error  Units
InstanceOfTest.testInstanceOf        avgt    5  1,972 ? 0,002  ns/op
InstanceOfTest.testIsAssignableFrom  avgt    5  1,991 ? 0,004  ns/op
InstanceOfTest.testIsInstance        avgt    5  1,972 ? 0,003  ns/op

เพื่อให้เราสามารถสรุป: อินสแตนซ์ของเร็วเท่าisInstance ()และisAssignableFrom ()ไม่ไกล (+ 0.9% เวลาดำเนินการ) ดังนั้นจึงไม่มีความแตกต่างอย่างแท้จริงกับสิ่งที่คุณเลือก


0

ตัวอย่างเกี่ยวกับวิธีที่จะแสดงมันในการดำเนินการ ...

@Test
public void isInstanceOf() {
    Exception anEx1 = new Exception("ex");
    Exception anEx2 = new RuntimeException("ex");
    RuntimeException anEx3 = new RuntimeException("ex");

    //Base case, handles inheritance
    Assert.assertTrue(anEx1 instanceof Exception);
    Assert.assertTrue(anEx2 instanceof Exception);
    Assert.assertTrue(anEx3 instanceof Exception);

    //Other cases
    Assert.assertFalse(anEx1 instanceof RuntimeException);
    Assert.assertTrue(anEx2 instanceof RuntimeException);
    Assert.assertTrue(anEx3 instanceof RuntimeException);
}

@Test
public void isAssignableFrom() {
    Exception anEx1 = new Exception("ex");
    Exception anEx2 = new RuntimeException("ex");
    RuntimeException anEx3 = new RuntimeException("ex");

    //Correct usage = The base class goes first
    Assert.assertTrue(Exception.class.isAssignableFrom(anEx1.getClass()));
    Assert.assertTrue(Exception.class.isAssignableFrom(anEx2.getClass()));
    Assert.assertTrue(Exception.class.isAssignableFrom(anEx3.getClass()));

    //Incorrect usage = Method parameter is used in the wrong order
    Assert.assertTrue(anEx1.getClass().isAssignableFrom(Exception.class));
    Assert.assertFalse(anEx2.getClass().isAssignableFrom(Exception.class));
    Assert.assertFalse(anEx3.getClass().isAssignableFrom(Exception.class));
}

-2

การทดสอบบางอย่างที่เราทำในการแสดงว่าทีมงานของเราทำงานได้เร็วกว่าA.class.isAssignableFrom(B.getClass()) B instanceof Aสิ่งนี้มีประโยชน์มากหากคุณต้องการตรวจสอบสิ่งนี้กับองค์ประกอบจำนวนมาก


13
หืมมมถ้าคุณมีคอขวดในinstanceofผมเชื่อว่าคุณมีปัญหาในการออกแบบร้ายแรง ...
sleske

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