Bir nesnenin bir dizi olup olmadığını yansıma kullanmadan nasıl görebilirim?


99

Java'da bir Nesnenin yansıma kullanmadan bir dizi olup olmadığını nasıl görebilirim? Ve yansıma kullanmadan tüm öğeleri nasıl yineleyebilirim?

Google GWT kullanıyorum, bu nedenle yansımayı kullanmama izin verilmiyor :(

Refelection kullanmadan aşağıdaki yöntemleri uygulamayı çok isterim:

private boolean isArray(final Object obj) {
  //??..
}

private String toString(final Object arrayObject) {
  //??..
}

BTW: JavaScript'i GWT dışı ortamlarda kullanabileceğim şekilde kullanmak da istemiyorum.

Yanıtlar:


249

Kullanabilirsiniz Class.isArray()

public static boolean isArray(Object obj)
{
    return obj!=null && obj.getClass().isArray();
}

Bu hem nesne hem de ilkel tür diziler için çalışır.

ToString için bir göz atın Arrays.toString. Dizi türünü kontrol etmeniz ve uygun toStringyöntemi çağırmanız gerekir .


1
Kullanarak dizi türünü bulabileceğinizi eklemeye değer obj.getClass().getComponentType().
Steve Chambers

68

Kullanabilirsiniz instanceof.

JLS 15.20.2 Tip Karşılaştırma Operatörü instanceof

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

Çalışma zamanında, sonucu instanceofoperatörü olan truedeğeri ise RelationalExpression değildir nullve referans için gölgeleri olabilir ReferenceType bir artırmadan ClassCastException. Aksi takdirde sonuç olur false.

Bu, bunun gibi bir şey yapabileceğiniz anlamına gelir:

Object o = new int[] { 1,2 };
System.out.println(o instanceof int[]); // prints "true"        

Sen nesne bir olup olmadığını kontrol etmek olurdu instanceof boolean[], byte[], short[], char[], int[], long[], float[], double[], veya Object[], tüm dizi türlerini tespit etmek istiyorum.

Ayrıca, an int[][]birdir instanceof Object[], dolayısıyla iç içe dizileri nasıl işlemek istediğinize bağlı olarak karmaşıklaşabilir.

İçin toString, java.util.Arraysbir sahip toString(int[])ve kullanabileceğiniz diğer aşırı yüklenmeleri. deepToString(Object[])İç içe diziler için de vardır .

public String toString(Object arr) {
   if (arr instanceof int[]) {
      return Arrays.toString((int[]) arr);
   } else //...
}

Çok tekrarlı olacak (ama hatta java.util.Arraysçok tekrarlayıcı ), ama dizilerle Java'da durum budur.

Ayrıca bakınız


Teşekkürler, bu kadar basit olduğunun farkında değildi. İnsstanceof'un T [] ile doğrudan kullanılamayacağını düşündüm :(
edbras

2
BTW: Bir şeyin bir dizi olup olmadığını keşfetmenin başka bir güzel yolunu da fark ettim Class.isArray () (Arrays.deepToString () 'de kullanılıyor).
edbras

@edbras: evet, Steve Kuo'nun aşağıda söylediği buydu. Çözümüm, API çağrısı yerine saf dilsel yapı kullanıyor.
poligenelubricants

İyi çalışıyor, sadece instanceof kullanmıyorum ama karşılaştırma olarak getClass kullanıyorum. Şuna benzer bir şey: if (array.getClass == int []. Class) {Arrays.toString ((int []) array); }
Herkese

@edbras: İşte java.util.Arraysböyle, evet. Bağlantı verdiğim kodu okuduğunuzu görüyorum.
poligenelubricants

35

Aşağıdaki kod kullanılarak bir dizinin her öğesine ayrı ayrı erişilebilir:

Object o=...;
if ( o.getClass().isArray() ) {
    for(int i=0; i<Array.getLength(o); i++){
        System.out.println(Array.get(o, i));
    }
}

Herhangi bir dizi için işe yarayacağından, bunun ne tür bir temel dizi olduğunu bilmenin gereksiz olduğuna dikkat edin.


2
isArray()Bundan 4 yıl önce gönderilen yanıtlar zaten yeterince kapsanmıştı.
Jason C

15
Bu cevap harika çünkü bize bir dizinin boyutunu nasıl alacağımızı ve içerik türü bilgisi olmadan bir öğeyi nasıl alacağımızı gösteriyor. Eminim çoğu insan daha önce hiç böyle kod yazmamıştı.
Christopher Yang

@MaartenBodewes - Bu bağlantıyı , GWT için "yansıma kullanmamanın" ne anlama geldiğine karar vermek için kullanırdım.
Stephen C

10

İlkel türdeki diziler arasında veya ilkel türden bir dizi ile başvuru türünün dizisi arasında alt tür oluşturma ilişkisi yoktur. Bkz. JLS 4.10.3 .

Bu nedenle, aşağıdaki herhangi bir türdenobj bir dizi olup olmadığını görmek için bir test olarak yanlıştır :

// INCORRECT!
public boolean isArray(final Object obj) {
    return obj instanceof Object[];
}

Spesifik olarak, obj1-D ilkel dizilerdeyse çalışmaz . (Yine de, daha yüksek boyutlu ilkel diziler için işe yarar, çünkü tüm dizi türleri alt türleridir Object. Ancak bu durumda tartışmalıdır.)

Google GWT kullanıyorum, bu nedenle yansımayı kullanmama izin verilmiyor :(

En iyi çözüm ( isArraysorunun dizi kısmına), neyin "yansıma kullanmak" olarak sayıldığına bağlıdır.

  • GWT'de arama obj.getClass().isArray(), yansıma 1'i kullanma olarak sayılmaz , bu nedenle en iyi çözüm budur.

  • Aksi takdirde, bir nesnenin bir dizi türüne sahip olup olmadığını anlamanın en iyi yolu, bir dizi instanceofifade kullanmaktır.

    public boolean isArray(final Object obj) {
        return obj instanceof Object[] || obj instanceof boolean[] ||
           obj instanceof byte[] || obj instanceof short[] ||
           obj instanceof char[] || obj instanceof int[] ||
           obj instanceof long[] || obj instanceof float[] ||
           obj instanceof double[];
    }
  • Ayrıca, nesnenin sınıfının adıyla aşağıdaki gibi uğraşmayı da deneyebilirsiniz, ancak çağrısı obj.getClass()yansımaya sınırlıdır.

    public boolean isArray(final Object obj) {
        return obj.getClass().toString().charAt(0) == '[';
    }

1 - Daha doğrusu, Class.isArrayyöntem bu sayfada GWT tarafından desteklendiği şekilde listelenmiştir .


0

Sınıfın herhangi bir Koleksiyon , Harita veya Diziyi temsil edip etmediğini kontrol etmek için bir yardımcı sınıf oluşturabilirsiniz.

  public static boolean isCollection(Class<?> rawPropertyType) {
        return Collection.class.isAssignableFrom(rawPropertyType) || 
               Map.class.isAssignableFrom(rawPropertyType) || 
               rawPropertyType.isArray();
 }

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.