Как узнать, к какому типу относится каждый объект в ArrayList <Object>?

87

У меня есть ArrayList, состоящий из различных элементов, импортированных из базы данных, состоящий из строк, чисел, чисел типа double и int. Есть ли способ использовать технику отражающего типа, чтобы узнать, какие данные хранятся в каждом элементе?

К вашему сведению: причина того, что существует так много типов данных, заключается в том, что это кусок Java-кода, который написан для реализации с разными БД.

Человек-ВолкДракон
источник

Ответы:

100

В C #:
исправлено по рекомендации Майка

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

В Java:

ArrayList<Object> list = ...;
for (Object o : list) {
    if (o instanceof Integer)) {
        handleInt((Integer o).intValue());
    }
    else if (o instanceof String)) {
        handleString((String)o);
    }
    ...
}
Франк Крюгер
источник
3
на самом деле вместо использования o.GetType () == typeof (int)) просто скажите if (o is int);
Майкл Браун
И если вы беспокоитесь о каждой наносекунде, «as» сэкономит вам немного по сравнению с «is» с гипсом.
Нил
47
Разве вы не можете просто сделать instanceofв случае с java?
Razor Storm
2
Для случая Integer это также должно быть Integer.class, я просто попробовал Integer.TYPE не работает.
Алан Тьюринг
(int) oне работает на Java. Выдает сообщение об ошибке Cannot cast from Object to int. (Integer o).intValue()Вместо этого используйте .
Макс
54

Вы можете использовать getClass()метод или instanceof. Например

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

или

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

Обратите внимание, что instanceof будет соответствовать подклассам. Например, of Cявляется подклассом A, тогда верно следующее:

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

Однако следующее будет ложным:

C c = new C();
assert !c.getClass().equals(A.class)
фаран
источник
45
for (Object object : list) {
    System.out.println(object.getClass().getName());
}
Фабиан Штег
источник
7
не забывайте про null, если это возможно в вашем списке. Вы получите исключение NullPointerExceptions из этого примера с нулями.
Джон Гарднер,
13

Вы почти никогда не захотите использовать что-то вроде:

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

потому что вы не учитываете возможные подклассы. Вы действительно хотите использовать Class # isAssignableFrom:

Object o = ...
if (Foo.class.isAssignableFrom(o)) {
    ...
}
Heath Borders
источник
5

В Java просто используйте оператор instanceof. Это также позаботится о подклассах.

ArrayList<Object> listOfObjects = new ArrayList<Object>();
for(Object obj: listOfObjects){
   if(obj instanceof String){
   }else if(obj instanceof Integer){
   }etc...
}
Рид Мак
источник
5
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());
            }
        }
    }
}
гончар
источник
4

Просто вызовите .getClass()каждого Objectв цикле.

К сожалению, в Java нет map(). :)

скипоппи
источник
3

Instanceof работает, если вы не зависите от определенных классов, но также помните, что у вас могут быть нули в списке, поэтому obj.getClass () завершится ошибкой, но instanceof всегда возвращает false для null.

Джон Гарднер
источник
3

Начиная с 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
            }
        });

Андрей
источник
2

вместо использования object.getClass().getName()вы можете использовать object.getClass().getSimpleName(), потому что он возвращает простое имя класса без имени пакета.

например,

Object[] intArray = { 1 }; 

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

дает,

java.lang.Integer
Integer
Суфиян Гори
источник
0

Вы говорите: «Это пишется фрагмент кода Java», из чего я делаю вывод, что все еще есть шанс, что вы могли бы спроектировать его по-другому.

ArrayList - это как набор вещей. Вместо того, чтобы заставлять instanceof или getClass каждый раз, когда вы берете объект из списка, почему бы не спроектировать систему так, чтобы вы получали тип объекта, когда вы получаете его из БД, и сохраняли его в коллекции соответствующего типа объект?

Или вы можете использовать одну из многих существующих библиотек доступа к данным, чтобы сделать это за вас.

обувать
источник
0

Если вы ожидаете, что данные будут числовыми в какой-либо форме, и все, что вам нужно сделать, это преобразовать результат в числовое значение, я бы предложил:

for (Object o:list) {
  Double.parseDouble(o.toString);
}
DJClayworth
источник