这里的主要问题是集合不会在定义中保留类型。这些类型仅在运行时可用。我想出了一个测试复杂集合的函数(尽管它有一个约束)。
检查对象是否为通用集合的实例。为了表示一个集合,
- 永远不上课
false
- 一个类,它不是一个集合,并返回
instanceof
评估结果
- 为了表示一个
List
或者Set
,列表类型随之而来的如{列表,整数冲了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;
}