简体   繁体   English

如何实例化列表<MyType> ?

[英]how to instanceof List<MyType>?

How can I get this sort of thing to work?我怎样才能让这种事情发挥作用? I can check if (obj instanceof List<?>) but not if (obj instanceof List<MyType>) .我可以检查 if (obj instanceof List<?>)但不能检查 if (obj instanceof List<MyType>) Is there a way this can be done?有没有办法做到这一点?

That is not possible because the datatype erasure at compile time of generics.这是不可能的,因为泛型编译时的数据类型擦除。 Only possible way of doing this is to write some kind of wrapper that holds which type the list holds:唯一可能的方法是编写某种包装器来保存列表所包含的类型:

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
}

You probably need to use reflection to get the types of them to check.您可能需要使用反射来检查它们的类型。 To get the type of the List: Get generic type of java.util.List获取列表的类型: 获取 java.util.List 的泛型类型

This could be used if you want to check that object is instance of List<T> , which is not empty:如果您想检查该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)))) {}

If you are verifying if a reference of a List or Map value of Object is an instance of a Collection, just create an instance of required List and get its class...如果您正在验证对象的 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());

If this can't be wrapped with generics (@Martijn's answer) it's better to pass it without casting to avoid redundant list iteration (checking the first element's type guarantees nothing).如果这不能用泛型包装(@Martijn 的答案),最好在不进行强制转换的情况下传递它以避免冗余列表迭代(检查第一个元素的类型不能保证任何内容)。 We can cast each element in the piece of code where we iterate the list.我们可以在迭代列表的代码段中转换每个元素。

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

You can use a fake factory to include many methods instead of using instanceof:您可以使用假工厂来包含许多方法,而不是使用 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);
    }
}

The major concern here is that the collections don't keep the type in the definition.这里的主要问题是集合不会在定义中保留类型。 The types are only available in runtime.这些类型仅在运行时可用。 I came up with a function to test complex collections (it has one constraint though).我想出了一个测试复杂集合的函数(虽然它有一个约束)。

Check if the object is an instance of a generic collection.检查对象是否是泛型集合的实例。 In order to represent a collection,为了代表一个集合,

  • No classes, always false没有课,总是false
  • One class, it is not a collection and returns the result of instanceof evaluation一个类,它不是一个集合并返回instanceof求值的结果
  • To represent a List or Set , the type of the list comes next eg {List, Integer} for List<Integer>要表示ListSet ,接下来是列表的类型,例如{List, Integer}表示List<Integer>
  • To represent a Map , the key and value types come next eg {Map, String, Integer} for Map<String, Integer>为了表示Map ,接下来是键和值类型,例如 {Map, String, Integer} 用于Map<String, Integer>

More complex use cases could be generated using the same rules.可以使用相同的规则生成更复杂的用例。 For example in order to represent List<Map<String, GenericRecord>> , it can be called as例如为了表示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);

Note that this implementation doesn't support nested types in the Map.请注意,此实现不支持 Map 中的嵌套类型。 Hence, the type of key and value should be a class and not a collection.因此,键和值的类型应该是一个类而不是一个集合。 But it shouldn't be hard to add it.但是添加它应该不难。

    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