如何检查对象是否为Java中的集合类型?


67

通过使用Java反射,我们可以轻松知道对象是否为数组。判断对象是否为集合(Set,List,Map,Vector ...)的最简单方法是什么?

Answers:


110
if (x instanceof Collection<?>){
}

if (x instanceof Map<?,?>){
}

4
注意?其中。您无法获得已删除的组件类型。如果您需要知道集合中可能包含哪种对象,则需要查看元素本身。
Thilo

1
没有元素时,如何找出集合中存在哪些对象?
MichalH '16

54

更新:这里有两种可能的情况:

  1. 您正在确定对象是否为集合;

  2. 您正在确定一个类是否是一个集合。

解决方案略有不同,但原理相同。您还需要定义什么才构成“集合”。实现CollectionMap将涵盖Java集合。

解决方案1:

public static boolean isCollection(Object ob) {
  return ob instanceof Collection || ob instanceof Map;
}

解决方案2:

public static boolean isClassCollection(Class c) {
  return Collection.class.isAssignableFrom(c) || Map.class.isAssignableFrom(c);
}

(1)也可以根据(2)来实现:

public static boolean isCollection(Object ob) {
  return ob != null && isClassCollection(ob.getClass());
}

我认为这两种方法的效率都不会大大不同。


塔任务的Becouse可以不“的instanceof”被sovled
书房bardadym

1
@den bardmadym,为什么不想使用instaceof?
Andrea Polci 2010年

我相信instanceof比isAssignableFrom更有效率,不是吗?
duduamar

我只会在必要时使用反射(isAssignableFrom),即在编译时不知道要测试的类。否则,恕我直言,一个简单的instanceof易于键入和读取。
Thilo

@duduamar可能您是正确的(应查看字节码)。确保isAssignableFrom的使用不能超过instanceof的性能
Andrea Polci 2010年

24

既然您在问题中提到反思,

boolean isArray = myArray.getClass().isArray();
boolean isCollection = Collection.class.isAssignableFrom(myList.getClass());
boolean isMap = Map.class.isAssignableFrom(myMap.getClass());

1
最佳答案IMO
Madbreaks '16

您也可以使用它,如果myArray引用为空,则将获得NPE 。因此需要检查是否为空。通过检查instanceof是没有必要的。参见stackoverflow.com/questions/2950319/…–
亚历山大

@Alexandr:其他答案都没有的else子句或检查null。至少有了这个答案,您不得不考虑使用null选项。
福皮

@Foumpie, obj instanceof Collection。我从未获得过NPE。我不需要检查null。如果obj为null ,则此语句的结果为false 。通过反射,无需显式检查即可获得NPE。
亚历山大

8

Java方便地使用instanceof运算符(JLS 15.20.2)来测试给定对象是否为给定类型。

 if (x instanceof List<?>) {   
    List<?> list = (List<?>) x;
    // do something with list
 } else if (x instanceof Collection<?>) {
    Collection<?> col = (Collection<?>) x;
    // do something with col
 }

这里应该提到一件事:在这种类型的结构中,以正确的顺序进行检查很重要。您会发现,如果在上面的代码段中交换了检查的顺序,代码仍然可以编译,但是将不再起作用。那是下面的代码不起作用:

 // DOESN'T WORK! Wrong order!
 if (x instanceof Collection<?>) {
    Collection<?> col = (Collection<?>) x;
    // do something with col
 } else if (x instanceof List<?>) { // this will never be reached!
    List<?> list = (List<?>) x;
    // do something with list
 }

问题是aList<?>是-a Collection<?>,因此它将通过第一个测试,并且else意味着它将永远不会到达第二个测试。您必须测试从最具体到最一般的类型


1
地图不扩展Collection。
Thilo

2
@Thilo:脑筋疲力;修改为List。重点仍然存在。
polygenelubricants 2010年

3

测试对象是否实现java.util.Collectionjava.util.Map。(Map因为它不是的子接口,所以必须单独进行测试Collection。)


1

您考虑过使用instanceof吗?就像说

if(myObject instanceof Collection) {
     Collection myCollection = (Collection) myObject;

尽管不是那种纯粹的OOP风格,但是它被广泛用于所谓的“类型升级”。


1
像我这样的老开发人员有时会倾向于在像这样的不可编译示例中使用java1.5之前的符号,尤其是在泛型符号没有增加任何价值的情况下。
Riduidel

添加的值是您明确声明了未知的类型。无法以1.5之前的方式传达此信息。
Max

@Max扮演复活者?我看到什么点您要搜索;-)无论如何,在Java 5+,Collection并且Collection<?>是等价的,因为他们所包含Object的实例。因此,这里没有泛型的附加值。
Riduidel '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.