我怎样才能让这种事情发挥作用?我可以检查 if(obj instanceof List<?>)
但不是 if (obj instanceof List<MyType>)
。有没有办法做到这一点?
问问题
123737 次
9 回答
53
这是不可能的,因为在泛型的编译时会擦除数据类型。唯一可能的方法是编写某种包装器来保存列表所包含的类型:
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;
}
}
于 2012-04-11T14:36:52.920 回答
45
if(!myList.isEmpty() && myList.get(0) instanceof MyType){
// MyType object
}
于 2016-07-23T08:46:02.190 回答
9
您可能需要使用反射来检查它们的类型。获取 List 的类型: 获取 java.util.List 的泛型类型
于 2012-04-11T14:40:53.027 回答
9
如果您想检查它是不是空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.
}
}
于 2018-01-03T15:57:27.753 回答
3
if (list instanceof List && ((List) list).stream()
.noneMatch((o -> !(o instanceof MyType)))) {}
于 2019-12-05T13:47:13.800 回答
1
如果这不能用泛型包装(@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 );
}
}
于 2017-04-07T14:12:07.737 回答
1
如果您正在验证 Object 的 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());
于 2017-01-15T02:27:00.400 回答
0
您可以使用假工厂来包含许多方法,而不是使用 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);
}
}
于 2017-10-24T11:09:03.743 回答
0
这里的主要问题是集合不保留定义中的类型。这些类型仅在运行时可用。我想出了一个测试复杂集合的函数(虽然它有一个约束)。
检查对象是否是泛型集合的实例。为了代表一个集合,
- 没有课,总是
false
- 一个类,它不是一个集合并返回
instanceof
评估结果 - 为了表示
List
orSet
,列表的类型紧随其后,例如{List, Integer}表示List<Integer>
- 为了表示 a
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;
}
于 2020-01-20T16:04:16.107 回答