Come faccio a sapere di che tipo è ogni oggetto in un ArrayList <Object>?


87

Ho un ArrayList composto da diversi elementi importati da un db, composto da stringhe, numeri, doppi e int. C'è un modo per utilizzare una tecnica del tipo di riflessione per scoprire cosa contiene ogni tipo di dati ogni elemento?

FYI: Il motivo per cui ci sono così tanti tipi di dati è che questo è un pezzo di codice java che viene scritto per essere implementato con diversi DB.

Risposte:


100

In C #:
risolto con la raccomandazione di 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);
    }
    ...
}

3
in realtà invece di usare o.GetType () == typeof (int)) dì semplicemente if (o is int);
Michael Brown

1
E se ti capita di essere preoccupato per ogni nanosecondo, "as" ti farà risparmiare alcuni rispetto a "is" con un cast.
Neil

47
Non puoi farlo solo instanceofnel caso Java?
Razor Storm

2
Per il caso Integer, dovrebbe anche essere Integer.class, ho appena provato Integer.TYPE non funziona.
alan turing

(int) onon funziona in Java. Produce il messaggio di errore Cannot cast from Object to int. Usa (Integer o).intValue()invece.
Max

54

Puoi usare il getClass()metodo o puoi usare instanceof. Per esempio

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

o

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

Nota che instanceof corrisponderà alle sottoclassi. Ad esempio, of Cè una sottoclasse di A, quindi sarà vero quanto segue:

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

Tuttavia, quanto segue sarà falso:

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

45
for (Object object : list) {
    System.out.println(object.getClass().getName());
}

7
non dimenticare null se è possibile nella tua lista. Otterrai NullPointerExceptions da questo esempio con valori null.
John Gardner,

13

Non vuoi quasi mai usare qualcosa come:

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

perché non stai tenendo conto delle possibili sottoclassi. Vuoi davvero usare Class # isAssignableFrom:

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

5

In Java è sufficiente utilizzare l'operatore instanceof. Questo si prenderà cura anche delle sottoclassi.

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

Basta chiamare .getClass()ciascuno Objectin un ciclo.

Sfortunatamente, Java non ha map(). :)


3

Instanceof funziona se non dipendi da classi specifiche, ma tieni presente anche che puoi avere valori nulli nell'elenco, quindi obj.getClass () fallirà, ma instanceof restituisce sempre false su null.


3

Poiché 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

invece di usare object.getClass().getName()puoi usare object.getClass().getSimpleName(), perché restituisce un semplice nome di classe senza un nome di pacchetto incluso.

per esempio,

Object[] intArray = { 1 }; 

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

dà,

java.lang.Integer
Integer

0

Dici "questo è un pezzo di codice java in fase di scrittura", da cui deduco che c'è ancora una possibilità che tu possa progettarlo in un modo diverso.

Avere un ArrayList è come avere una raccolta di cose. Piuttosto che forzare l'istanza di o getClass ogni volta che prendi un oggetto dalla lista, perché non progettare il sistema in modo da ottenere il tipo di oggetto quando lo recuperi dal DB e memorizzarlo in una raccolta del tipo appropriato di oggetto?

Oppure puoi usare una delle tante librerie di accesso ai dati esistenti per farlo per te.


0

Se ti aspetti che i dati siano numerici in qualche forma e tutto ciò che ti interessa è convertire il risultato in un valore numerico, suggerirei:

for (Object o:list) {
  Double.parseDouble(o.toString);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.