Java dizi yansıması: isArray vs. instanceof


177

Kullanmak arasında bir tercih veya davranış farkı var mı:

if(obj.getClass().isArray()) {}

ve

if(obj instanceof Object[]) {}

?

Yanıtlar:


203

Çoğu durumda, instanceofbir nesnenin dizi olup olmadığını test etmek için operatörü kullanmalısınız .

Genellikle, bir nesnenin türünü derleme zamanında bilinen belirli bir türe indirmeden önce test edersiniz. Örneğin, belki bir Integer[]veya bir ile çalışabilecek bir kod yazdınız int[]. Oyuncularınızı aşağıdakilerle korumak istersiniz instanceof:

if (obj instanceof Integer[]) {
    Integer[] array = (Integer[]) obj;
    /* Use the boxed array */
} else if (obj instanceof int[]) {
    int[] array = (int[]) obj;
    /* Use the primitive array */
} else ...

JVM seviyesinde, instanceofoperatör çoğu JVM uygulamasında optimize edilen belirli bir "örnek" bayt koduna çevirir .

Daha nadir durumlarda, bilinmeyen türlerde bir nesne grafiğini hareket ettirmek için yansıma kullanıyor olabilirsiniz. Bu gibi durumlarda isArray(), derleme zamanında bileşen türünü bilmediğiniz için yöntem yararlı olabilir; örneğin, bir tür serileştirme mekanizması uyguluyor olabilir ve türden bağımsız olarak dizinin her bileşenini aynı serileştirme yöntemine geçirebilirsiniz.

İki özel durum vardır: boş referanslar ve ilkel dizilere referanslar.

Bir boş başvuru neden olur instanceof sonuçlanması falseise, isArraybir atar NullPointerException.

İlkel bir diziye instanceofuygulandığında false, sağ taraftaki bileşen türü bileşen türü ile tam olarak eşleşmediği sürece verim elde edilir . Aksine, herhangi bir bileşen türü için isArray()dönecektir true.


7
Evet, ama ne kadar fark yaratacak? Bu benim için bir mikro optimizasyon gibi geliyor.
Michael Myers

2
Eğer iddia varsa @Dims obj instanceof int[]verimi falsebir atamak int[]için obj, yanılıyorsunuz.
erickson

4
Üzgünüm anlamına geliyordu obj instanceof Object[]verimi falseise Object obj = new int[7].
Dims

3
Doğru, Java'da, ilkel veri türleri nesne değildir ve genişlemez java.lang.Object, bu nedenle mantıklıdır. Ancak instanceofyine de ilkel dizileri test etmek için kullanılabilir.
erickson

4
-1: Genelde, ilkel diziler olduğu için arama dizisi isArray()kullanılmalıdır. Çok genel olmayan bir durumda, sadece nesne dizilerine sahip olmak, instanceofyüksek performanslı bir alternatif sunar.
Sam Harwell

33

İkinci durumda, obj null olursa, bir NullPointerException değil false alırsınız.


8

Eğer objtür int[]ise, o zaman bir dizi olacak, Classancak bir örneği olmayacaktır Object[]. Peki ne yapmak istiyorsun obj. Eğer yayınlayacaksan, git instanceof. Yansımayı kullanacaksanız, kullanın .getClass().isArray().


4

getClass().isArray() Sun Java 5 veya 6 JRE'de IBM'den önemli ölçüde daha yavaştır.

O kadar kullanarak bu clazz.getName().charAt(0) == '['hızlı Sun JVM üzerindedir.


10
Bağlanabileceğiniz herhangi bir istatistik, örnek olay veya başka bir kanıt var mı?
David Citron

4

Geçenlerde Groovy uygulamasını JDK 5'ten JDK 6'ya yükseltme konusunda bir sorunla karşılaştım isArray(). JDK6'da kullanım başarısız oldu:

MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...

instanceof Object[]Bunu düzeltmek için değiştirme .


Bu anlamlı değil. isArraybir yöntemdir Class, değil Type, bu yüzden elbette GenericArrayTypeImplbu yöntem yoktur. Ve getClassasla bir olmayan dönemezsiniz Class Type, bu yüzden (veya Groovy ??) bunu almak için yanlış bir şey yapmış olmalısınız, her Typebiri bir olduğunu varsayalım Class.
kaqqao

3

Java dizisi yansıması, üzerinde "instanceof" yapmak için kullanılabilir Sınıf örneğinin bulunmadığı durumlar içindir. Örneğin, JPA gibi sınıfın yeni bir örneğine değerler enjekte eden bir tür enjeksiyon çerçevesi yazıyorsanız, isArray () işlevini kullanmanız gerekir.

Bu konuda Aralık ayının başlarında blog yazdım. http://blog.adamsbros.org/2010/12/08/java-array-reflection/


2

Yansıtıcı bir çözüm ile yansıtıcı olmayan bir çözüm arasında bir seçeneğiniz varsa, asla yansıtıcı olanı (Sınıf nesnelerini içeren) seçmeyin. Bu "Yanlış" ya da herhangi bir şey değil, ama yansımayı içeren her şey genellikle daha az açık ve daha az açıktır.


Ee, "instanceof" de bir tür yansımadır (ya da en azından içgözlem), ama ben de anlıyorum.
David Citron

Ayrıca, genellikle daha yavaştır.
Mad Physicist

0

İkisi arasında bulabildiğim davranış farkı yok (bariz boş durum dışında). Hangi sürümü tercih edeceğim, ikinci ile giderdim. Bunu Java'da yapmanın standart yoludur.

Kodunuzun okuyucularını karıştırırsa ( String[] instanceof Object[]doğru olduğu için), kod inceleyenleri sormaya devam ederse daha açık olmak için ilkini kullanmak isteyebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.