<MyType> Listesinin örneği nasıl yapılır?


Yanıtlar:


49

Bu mümkün değildir çünkü jeneriklerin derleme zamanında veri türü silinir. Bunu yapmanın tek olası yolu, listenin içerdiği türü tutan bir tür sarmalayıcı yazmaktır:

public class GenericList <T> extends ArrayList<T>
{
     private Class<T> genericType;

     public GenericList(Class<T> c)
     {
          this.genericType = c;
     }

     public Class<T> getGenericType()
     {
          return genericType;
     }
}

Teşekkürler, sanırım genel türü her iki öğeyi de kontrol etmek ve kontrol etmek için aradığım işleve geçireceğim.
Rocky Kasnak

Bir örnekle detaylandırır mısınız
Thirumal

31
if(!myList.isEmpty() && myList.get(0) instanceof MyType){
    // MyType object
}

7
... ve boş bir liste için? Düşünceler?
Gewure

Evet. Boş liste için mevcut tek seçenek budur. stackoverflow.com/questions/1942644/…
Sathish

12
Bu yanıt güvenli değil, çünkü 0 öğesi bir MyType olsa bile, diğer öğeler başka türler olabilir. Örneğin, liste ArrayList <Object> olarak bildirilmiş, ardından bir MyType eklenmiş ve ardından bir String eklenmiştir.
Adam Gawne-Cain

@ AdamGawne-Cain Güvenli değil, ama ne yazık ki liste hakkında fazla bir şey bilmeyen insanlar için tek çözüm. Örneğin - valuedönen bir yerel değişkenim var Objectve kontrol etmem gerekiyor - bu bir liste ise, eğer öyleyse, arayüzümün liste tipi örneğinin olup olmadığını kontrol et. Burada hiçbir sarmalayıcı veya parametrik tip yararlı değildir.
SocketByte

MyList nerede ilan edilir?
IgorGanapolsky


6

Bu , boş olmayan objectörneğinin olup olmadığını kontrol etmek isterseniz kullanılabilir List<T>:

if(object instanceof List){
    if(((List)object).size()>0 && (((List)object).get(0) instanceof MyObject)){
        // The object is of List<MyObject> and is not empty. Do something with it.
    }
}

2
    if (list instanceof List && ((List) list).stream()
                                             .noneMatch((o -> !(o instanceof MyType)))) {}

1

Bir Nesnenin Liste veya Harita değerinin referansının Koleksiyonun bir örneği olup olmadığını doğruluyorsanız, gerekli Listenin bir örneğini oluşturun ve sınıfını alın ...

Set<Object> setOfIntegers = new HashSet(Arrays.asList(2, 4, 5));
assetThat(setOfIntegers).instanceOf(new ArrayList<Integer>().getClass());

Set<Object> setOfStrings = new HashSet(Arrays.asList("my", "name", "is"));
assetThat(setOfStrings).instanceOf(new ArrayList<String>().getClass());

Aramalarınızdan noktası nedir setOfIntegersve setOfStrings?
DanielM

@DanielM, örneği güncelledi. Bu referansları kullanıyor olmalı! Teşekkürler!
Marcello de Sales

1

Eğer bu jeneriklerle sarılamıyorsa (@ Martijn'in cevabı) gereksiz liste yinelemesinden kaçınmak için çevrim yapmadan geçmek daha iyidir (ilk elemanın türünün kontrol edilmesi hiçbir şeyi garanti etmez). Her bir öğeyi listeyi yinelediğimiz kod parçasına yerleştirebiliriz.

Object attVal = jsonMap.get("attName");
List<Object> ls = new ArrayList<>();
if (attVal instanceof List) {
    ls.addAll((List) attVal);
} else {
    ls.add(attVal);
}

// far, far away ;)
for (Object item : ls) {
    if (item instanceof String) {
        System.out.println(item);
    } else {
        throw new RuntimeException("Wrong class ("+item .getClass()+") of "+item );
    }
}

0

İnstanceof kullanmak yerine birçok yöntemi dahil etmek için sahte bir fabrika kullanabilirsiniz:

public class Message1 implements YourInterface {
   List<YourObject1> list;
   Message1(List<YourObject1> l) {
       list = l;
   }
}

public class Message2 implements YourInterface {
   List<YourObject2> list;
   Message2(List<YourObject2> l) {
       list = l;
   }
}

public class FactoryMessage {
    public static List<YourInterface> getMessage(List<YourObject1> list) {
        return (List<YourInterface>) new Message1(list);
    }
    public static List<YourInterface> getMessage(List<YourObject2> list) {
        return (List<YourInterface>) new Message2(list);
    }
}

0

Buradaki en büyük endişe, koleksiyonların türü tanımda tutmamasıdır. Türler yalnızca çalışma zamanında mevcuttur. Karmaşık koleksiyonları test etmek için bir işlev buldum (yine de bir kısıtlaması var).

Nesnenin genel bir koleksiyonun bir örneği olup olmadığını kontrol edin. Bir koleksiyonu temsil etmek için,

  • Her zaman sınıf yok false
  • Bir sınıf, bu bir koleksiyon değildir ve instanceofdeğerlendirme sonucunu döndürür
  • Bir Listveya temsil etmek için Set, listenin türü sonra gelir örn. {Liste, Tamsayı} içinList<Integer>
  • A'yı temsil etmek için Map, anahtar ve değer türleri daha sonra gelir, ör. {Eşleme, Dize, Tamsayı} içinMap<String, Integer>

Aynı kurallar kullanılarak daha karmaşık kullanım durumları oluşturulabilir. Örneğin temsil etmek için List<Map<String, GenericRecord>>şu şekilde adlandırılabilir:

    Map<String, Integer> map = new HashMap<>();
    map.put("S1", 1);
    map.put("S2", 2);
    List<Map<String, Integer> obj = new ArrayList<>();
    obj.add(map);
    isInstanceOfGenericCollection(obj, List.class, List.class, Map.class, String.class, GenericRecord.class);

Bu uygulamanın Haritadaki iç içe geçmiş türleri desteklemediğini unutmayın. Bu nedenle, anahtarın ve değerin türü bir koleksiyon değil, bir sınıf olmalıdır. Ama eklemek zor olmamalı.

    public static boolean isInstanceOfGenericCollection(Object object, Class<?>... classes) {
        if (classes.length == 0) return false;
        if (classes.length == 1) return classes[0].isInstance(object);
        if (classes[0].equals(List.class))
            return object instanceof List && ((List<?>) object).stream().allMatch(item -> isInstanceOfGenericCollection(item, Arrays.copyOfRange(classes, 1, classes.length)));
        if (classes[0].equals(Set.class))
            return object instanceof Set && ((Set<?>) object).stream().allMatch(item -> isInstanceOfGenericCollection(item, Arrays.copyOfRange(classes, 1, classes.length)));
        if (classes[0].equals(Map.class))
            return object instanceof Map &&
                    ((Map<?, ?>) object).keySet().stream().allMatch(classes[classes.length - 2]::isInstance) &&
                    ((Map<?, ?>) object).values().stream().allMatch(classes[classes.length - 1]::isInstance);
        return false;
    }
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.