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;
     }
}
Martijn Courteaux
sumber
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
}
Sathish
sumber
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
9

Anda mungkin perlu menggunakan refleksi untuk mendapatkan jenisnya untuk diperiksa. Untuk mendapatkan tipe List: Dapatkan tipe generik java.util.List

evanwong
sumber
2
Sejauh yang saya tahu, itu hanya berfungsi untuk bidang, tetapi +1 untuk menyebutkannya.
Tim Pote
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.
    }
}
Ivo Stoyanov
sumber
2
    if (list instanceof List && ((List) list).stream()
                                             .noneMatch((o -> !(o instanceof MyType)))) {}
dlaagniechy.dll
sumber
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());
Marcello de Sales
sumber
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 );
    }
}
kinjelom
sumber
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);
    }
}
LeLe
sumber
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;
    }
Iraj Hedayati
sumber