簡體   English   中英

如何實例化列表<MyType> ?

[英]how to instanceof List<MyType>?

我怎樣才能讓這種事情發揮作用? 我可以檢查 if (obj instanceof List<?>)但不能檢查 if (obj instanceof List<MyType>) 有沒有辦法做到這一點?

這是不可能的,因為泛型編譯時的數據類型擦除。 唯一可能的方法是編寫某種包裝器來保存列表所包含的類型:

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;
     }
}
if(!myList.isEmpty() && myList.get(0) instanceof MyType){
    // MyType object
}

您可能需要使用反射來檢查它們的類型。 獲取列表的類型: 獲取 java.util.List 的泛型類型

如果您想檢查該object是否為非空的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.
    }
}
    if (list instanceof List && ((List) list).stream()
                                             .noneMatch((o -> !(o instanceof MyType)))) {}

如果您正在驗證對象的 List 或 Map 值的引用是否是 Collection 的實例,只需創建所需 List 的實例並獲取其類...

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

如果這不能用泛型包裝(@Martijn 的答案),最好在不進行強制轉換的情況下傳遞它以避免冗余列表迭代(檢查第一個元素的類型不能保證任何內容)。 我們可以在迭代列表的代碼段中轉換每個元素。

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

您可以使用假工廠來包含許多方法,而不是使用 instanceof:

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

這里的主要問題是集合不會在定義中保留類型。 這些類型僅在運行時可用。 我想出了一個測試復雜集合的函數(雖然它有一個約束)。

檢查對象是否是泛型集合的實例。 為了代表一個集合,

  • 沒有課,總是false
  • 一個類,它不是一個集合並返回instanceof求值的結果
  • 要表示ListSet ,接下來是列表的類型,例如{List, Integer}表示List<Integer>
  • 為了表示Map ,接下來是鍵和值類型,例如 {Map, String, Integer} 用於Map<String, Integer>

可以使用相同的規則生成更復雜的用例。 例如為了表示List<Map<String, GenericRecord>> ,它可以被稱為

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

請注意,此實現不支持 Map 中的嵌套類型。 因此,鍵和值的類型應該是一個類而不是一個集合。 但是添加它應該不難。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM