如何找出 ArrayList < Object > 中每个对象的类型?

我有一个由从 db 导入的不同元素组成的 ArrayList,它由字符串、数字、双精度数和整型数组成。有没有一种方法可以使用反射类型技术来找出每个元素所持有的每种类型的数据?

供参考: 数据类型如此之多的原因是,这是一段用不同数据库实现的 Java 代码。

269528 次浏览

Just call .getClass() on each Object in a loop.

Unfortunately, Java doesn't have map(). :)

In C#:
Fixed with recommendation from Mike

ArrayList list = ...;
// List<object> list = ...;
foreach (object o in list) {
if (o is int) {
HandleInt((int)o);
}
else if (o is string) {
HandleString((string)o);
}
...
}

In Java:

ArrayList<Object> list = ...;
for (Object o : list) {
if (o instanceof Integer)) {
handleInt((Integer o).intValue());
}
else if (o instanceof String)) {
handleString((String)o);
}
...
}
for (Object object : list) {
System.out.println(object.getClass().getName());
}

You can use the getClass() method, or you can use instanceof. For example

for (Object obj : list) {
if (obj instanceof String) {
...
}
}

or

for (Object obj : list) {
if (obj.getClass().equals(String.class)) {
...
}
}

Note that instanceof will match subclasses. For instance, of C is a subclass of A, then the following will be true:

C c = new C();
assert c instanceof A;

However, the following will be false:

C c = new C();
assert !c.getClass().equals(A.class)

Instanceof works if you don't depend on specific classes, but also keep in mind that you can have nulls in the list, so obj.getClass() will fail, but instanceof always returns false on null.

You say "this is a piece of java code being written", from which I infer that there is still a chance that you could design it a different way.

Having an ArrayList is like having a collection of stuff. Rather than force the instanceof or getClass every time you take an object from the list, why not design the system so that you get the type of the object when you retrieve it from the DB, and store it into a collection of the appropriate type of object?

Or, you could use one of the many data access libraries that exist to do this for you.

You almost never want you use something like:

Object o = ...
if (o.getClass().equals(Foo.class)) {
...
}

because you aren't accounting for possible subclasses. You really want to use Class#isAssignableFrom:

Object o = ...
if (Foo.class.isAssignableFrom(o)) {
...
}

If you expect the data to be numeric in some form, and all you are interested in doing is converting the result to a numeric value, I would suggest:

for (Object o:list) {
Double.parseDouble(o.toString);
}

In Java just use the instanceof operator. This will also take care of subclasses.

ArrayList<Object> listOfObjects = new ArrayList<Object>();
for(Object obj: listOfObjects){
if(obj instanceof String){
}else if(obj instanceof Integer){
}etc...
}
import java.util.ArrayList;


/**
* @author potter
*
*/
public class storeAny {


/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub


ArrayList<Object> anyTy=new ArrayList<Object>();
anyTy.add(new Integer(1));
anyTy.add(new String("Jesus"));
anyTy.add(new Double(12.88));
anyTy.add(new Double(12.89));
anyTy.add(new Double(12.84));
anyTy.add(new Double(12.82));


for (Object o : anyTy) {
if(o instanceof String){
System.out.println(o.toString());
} else if(o instanceof Integer) {
System.out.println(o.toString());
} else if(o instanceof Double) {
System.out.println(o.toString());
}
}
}
}

instead of using object.getClass().getName() you can use object.getClass().getSimpleName(), because it returns a simple class name without a package name included.

for instance,

Object[] intArray = { 1 };


for (Object object : intArray) {
System.out.println(object.getClass().getName());
System.out.println(object.getClass().getSimpleName());
}

gives,

java.lang.Integer
Integer

Since Java 8


mixedArrayList.forEach((o) -> {
String type = o.getClass().getSimpleName();
switch (type) {
case "String":
// treat as a String
break;
case "Integer":
// treat as an int
break;
case "Double":
// treat as a double
break;
...
default:
// whatever
}
});