java: Class.isInstance vs Class.isAssignableFrom


232

Biarkan clazzbeberapa Classdan objbeberapa Object.

Adalah

clazz.isAssignableFrom(obj.getClass())

selalu sama dengan

clazz.isInstance(obj)

?

Jika tidak, apa perbedaannya?


26
jika obj == null, yang kedua mengembalikan false, yang pertama tidak. ;)
Peter Lawrey

21
@ PeterLawrey, yang pertama akan melempar NullPointerExceptionif obj == null.
ryvantage

Ditemukan beberapa jawaban dengan sampel dari hrere: mytechnotes.biz/2012/07/…
Paramesh Korrakuti

4
Untuk para pembaca: Anda akan memasuki lubang hitam yang dalam, gelap, tempat Anda tidak akan pernah bisa melarikan diri. Perbedaannya tidak terbatas. Menyerah sekarang selagi masih bisa: stackoverflow.com/q/496928/1599699
Andrew

@ParameshKorrakuti nama domain berubah menjadi tshikatshikaaa.blogspot.com/2012/07/…
Jérôme Verstrynge

Jawaban:


222

clazz.isAssignableFrom(Foo.class)akan benar setiap kali kelas yang diwakili oleh clazzobjek adalah superclass atau superinterface dari Foo.

clazz.isInstance(obj)akan benar setiap kali objek objadalah turunan dari kelas clazz.

Itu adalah:

clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)

selalu benar selama clazzdan objtidak kosong.


3
ini merindukan kasus di mana Foo sama dengan clazz - dalam hal ini mengembalikan benar: jawaban terpilih Pauls di bawah ini mengoreksi ini
Rhubarb

3
Saya setuju bahwa ketika clazz adalah Foo, maka clazz.isAssignableFrom (Foo.class) benar. Di mana saya katakan sebaliknya?
uckelman

5
@Gili Ini bukan apa yang dikatakan uckelman. Harap baca kembali jawabannya.
Puce

2
Byte b = 3; Comparable.class.isAssignableFrom(b.getClass()) == Comparable.class.isInstance(b)); -> itu benar juga untuk antarmuka.
Puce

1
Teknis: Jika objadalah nullmaka clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)akan melempar NullPointerExceptiondan tidak kembali true.
Andrew Macheret

196

Kedua jawaban ada di stadion baseball tetapi tidak ada jawaban yang lengkap.

MyClass.class.isInstance(obj)adalah untuk memeriksa sebuah instance. Ini mengembalikan true ketika parameter obj non-null dan dapat dilemparkan ke MyClasstanpa menaikkan a ClassCastException. Dengan kata lain, obj adalah turunan dari MyClassatau subkelasnya.

MyClass.class.isAssignableFrom(Other.class)akan mengembalikan true jika MyClasssama dengan, atau superclass atau superinterface dari Other,. Otherbisa berupa kelas atau antarmuka. Itu menjawab benar jika Otherdapat dikonversi ke a MyClass.

Sedikit kode untuk diperagakan:

public class NewMain
{
    public static void main(String[] args)
    {
        NewMain nm = new NewMain();
        nm.doit();
    }

    class A { }

    class B extends A { }

    public void doit()
    {
        A myA = new A();
        B myB = new B();
        A[] aArr = new A[0];
        B[] bArr = new B[0];

        System.out.println("b instanceof a: " + (myB instanceof A)); // true
        System.out.println("b isInstance a: " + A.class.isInstance(myB)); //true
        System.out.println("a isInstance b: " + B.class.isInstance(myA)); //false
        System.out.println("b isAssignableFrom a: " + A.class.isAssignableFrom(B.class)); //true
        System.out.println("a isAssignableFrom b: " + B.class.isAssignableFrom(A.class)); //false
        System.out.println("bArr isInstance A: " + A.class.isInstance(bArr)); //false
        System.out.println("bArr isInstance aArr: " + aArr.getClass().isInstance(bArr)); //true
        System.out.println("bArr isAssignableFrom aArr: " + aArr.getClass().isAssignableFrom(bArr.getClass())); //true
    }
}

10
Mengapa dalam contoh Anda "b isAssignableFrom a:" tetapi kode A.class.isAssignableFrom(B.class)? Saya bingung dengan output :)
Roman Truba

4
ummm ... dalam semua contoh Anda "instanceOf" mengembalikan true iff "isAssignableFrom" mengembalikan true ... Saya tidak melihat perbedaannya dengan cara ini.
pengembang android

2
Hati-hati teks yang dicetak tidak cocok dengan kode dan dapat membingungkan ... Contoh: "System.out.println (" b isAssignableFrom a: "+ A.class.isAssignableFrom (B.class));"
polster

21
@ Paul Jawabannya, seperti, tidak membantu, karena pembaca dibiarkan bertanya-tanya "apa perbedaan antara objek menjadi turunan dari subkelas kelas dan jenis objek yang dapat dikonversi ke kelas?" Tentunya, Anda dapat melihat bahwa Anda telah meninggalkan pembaca dengan banyak pertanyaan setelah membaca jawaban Anda ketika ia tiba di halaman ini. Jawaban yang lebih baik sebenarnya akan menjelaskan perbedaan (atau ketiadaan). Jika tidak ada perbedaan, jawabannya harus langsung menyatakan, "tidak ada perbedaan praktis."
Aleksandr Dubinsky

2
Lebih penting lagi, pembaca dibiarkan bertanya-tanya apa sih yang digunakan untuk tujuan mereka. Menurut komentar dalam pertanyaan, isAssignableFrom()melempar a NullPointerExceptionjika objek tersebut null, sedangkan isInstance()hanya mengembalikan false. Itu jawaban yang sebenarnya.
Andrew

6

Saya pikir hasilnya untuk keduanya harus selalu sama. Perbedaannya adalah bahwa Anda memerlukan instance kelas untuk digunakan isInstancetetapi hanya Classobjek yang akan digunakan isAssignableFrom.


Ini tidak 100% benar. Comparable.class.isAssignableFrom(Byte.class) == truetapi Byte.class.isInstance(Comparable.class) == false. Dengan kata lain, isInstance()tidak simetris untuk antarmuka, hanya untuk subkelas.
Gili

6
@ Geili: Ada yang salah di sana. Byte.class.isInstance(Comparable.class)salah karena Classobjek bukan turunan dari Byte. Perbandingan yang benar Comparable.class.isAssignableFrom(Byte.class)adalah Comparable.class.isInstance((byte) 1), yang benar.
ColinD

1
Saya tidak setuju. Jika Anda mencari Javadoc ByteAnda akan menemukan itu meluas Numberdan kelas. (byte) 1tidak setara dengan Byte. Yang pertama adalah primitif. Yang terakhir adalah Kelas.
Gili

2
@Gili: Autoboxing gips primitif byteke Bytekarena jenis parameter isInstanceadalah Object.
ColinD

2
Baik. Poin asli saya adalah bahwa panggilan tidak persis simetris satu sama lain, tetapi setelah membaca kembali jawaban Anda, Anda tidak pernah membuat pernyataan ini sehingga Anda benar.
Gili

6

Untuk singkatnya, kita dapat memahami dua API ini seperti di bawah ini:

  1. X.class.isAssignableFrom(Y.class)

Jika Xdan Yadalah kelas yang sama, atau Xmerupakan Y's kelas super atau super antarmuka, kembali benar, jika tidak, palsu.

  1. X.class.isInstance(y)

Say yadalah turunan dari kelas Y, jika Xdan Yadalah kelas yang sama, atau Xadalah Ykelas super atau antarmuka super, mengembalikan true, jika tidak, false.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.