bagaimana cara instance dari List <MyType>?


Jawaban:


49

Itu tidak mungkin karena penghapusan tipe data pada waktu kompilasi obat generik. Satu-satunya cara yang mungkin untuk melakukan ini adalah dengan menulis semacam pembungkus yang menampung jenis yang dipegang daftar:

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;
     }
}

Terima kasih, saya rasa saya hanya akan meneruskan tipe generik ke dalam fungsi yang saya panggil untuk memeriksa dan memeriksa kedua item.
Rocky Pulley

Bisakah Anda menjelaskannya dengan contoh
Thirumal

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

7
... dan untuk daftar kosong? Refleksi?
Gewure

Yeap. Itulah satu-satunya pilihan yang tersedia untuk daftar kosong. stackoverflow.com/questions/1942644/…
Sathish

12
Jawaban ini tidak aman, karena meskipun 0 elemen adalah MyType, elemen lainnya bisa jadi tipe lain. Misalnya, mungkin daftar dideklarasikan sebagai ArrayList <Object>, lalu MyType ditambahkan, lalu String ditambahkan.
Adam Gawne-Cain

@ AdamGawne-Cain Ini tidak aman, tapi sayangnya satu-satunya solusi bagi orang yang TIDAK tahu banyak tentang daftar. Misalnya - Saya memiliki variabel lokal valueyang kembali Object, dan saya perlu memeriksa - jika itu adalah daftar, jika ada, periksa apakah contoh jenis daftar antarmuka saya. Tidak ada jenis pembungkus atau parameter yang berguna di sini.
SocketByte

Di mana myList dideklarasikan?
IgorGanapolsky


6

Ini bisa digunakan jika Anda ingin memeriksanya object itu instance List<T>, yang tidak kosong:

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

Jika Anda memverifikasi apakah referensi dari nilai Daftar atau Peta Objek adalah turunan dari Koleksi, cukup buat contoh Daftar yang diperlukan dan dapatkan kelasnya ...

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());

Apa gunanya setOfIntegersdan setOfStrings?
DanielM

@DanielM baru saja memperbarui sampel. Itu pasti menggunakan referensi itu! Terima kasih!
Marcello de Sales

1

Jika ini tidak dapat digabungkan dengan generik (jawaban @ Martijn), lebih baik meneruskannya tanpa casting untuk menghindari iterasi daftar yang berlebihan (memeriksa jenis elemen pertama tidak menjamin apa pun). Kita dapat mentransmisikan setiap elemen dalam potongan kode tempat kita mengulang daftar.

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

Anda dapat menggunakan pabrik palsu untuk memasukkan banyak metode daripada menggunakan contoh:

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

Perhatian utama di sini adalah bahwa koleksi tidak menyimpan tipe dalam definisi. Jenis ini hanya tersedia saat runtime. Saya datang dengan fungsi untuk menguji koleksi yang kompleks (meskipun ada satu kendala).

Periksa apakah objek tersebut merupakan turunan dari koleksi generik. Untuk mewakili sebuah koleksi,

  • Tidak ada kelas, selalu false
  • Satu kelas, itu bukan koleksi dan mengembalikan hasil instanceof evaluasi
  • Untuk mewakili a Listatau Set, jenis daftar datang berikutnya, misalnya {List, Integer} untukList<Integer>
  • Untuk merepresentasikan a Map, kunci dan tipe nilai datang berikutnya misalnya {Map, String, Integer} forMap<String, Integer>

Kasus penggunaan yang lebih kompleks dapat dibuat menggunakan aturan yang sama. Misalnya untuk merepresentasikan List<Map<String, GenericRecord>>dapat disebut sebagai

    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);

Perhatikan bahwa implementasi ini tidak mendukung tipe bertingkat di Peta. Oleh karena itu, jenis kunci dan nilai harus berupa kelas dan bukan koleksi. Tetapi seharusnya tidak sulit untuk menambahkannya.

    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;
    }
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.