Un modo semplice per ottenere il tipo di class wrapper in Java

Ho un pezzo di codice in cui ho bisogno di passare la class di un campo in un metodo. A causa della meccanica del mio codice, posso gestire solo oggetti di riferimento e non primitive. Voglio un modo semplice per determinare se il tipo di un Field è primitivo e scambiarlo con la class wrapper appropriata. Quindi in codice quello che faccio finora è qualcosa del genere:

 Field f = getTheField(); // Dummy method that returns my Field Class c = f.getType(); if (c == int.class) { c = Integer.class; } else if (c == float.class) { c = Float.class; } // etc myMethod(c); 

Funziona bene, tranne per il fatto che ho bisogno di verificare esplicitamente tutti i tipi primitivi e scambiarli con la class wrapper appropriata. Ora so che non ci sono molti tipi primitivi e non sarà un problema semplicemente elencarli tutti, ma mi chiedevo se esistesse un modo più semplice ed elegante di farlo.

Io uso la libreria delle raccolte di Google nella mia risposta, perché sono viziato in quel modo, ma puoi probabilmente vedere come farlo con semplici HashMaps, se preferisci.

  // safe because both Long.class and long.class are of type Class @SuppressWarnings("unchecked") private static  Class wrap(Class c) { return c.isPrimitive() ? (Class) PRIMITIVES_TO_WRAPPERS.get(c) : c; } private static final Map, Class> PRIMITIVES_TO_WRAPPERS = new ImmutableMap.Builder, Class>() .put(boolean.class, Boolean.class) .put(byte.class, Byte.class) .put(char.class, Character.class) .put(double.class, Double.class) .put(float.class, Float.class) .put(int.class, Integer.class) .put(long.class, Long.class) .put(short.class, Short.class) .put(void.class, Void.class) .build(); 

È strano che non esista nulla nel JDK per questo, ma in effetti non funziona.

EDIT: avevo completamente dimenticato che abbiamo rilasciato questo:

http://google.github.io/guava/releases/21.0/api/docs/com/google/common/primitives/Primitives.html

Ha il metodo wrap (), più unwrap () e alcune altre cose secondarie.

Apache Commons Lang ha un metodo di utilità per fare questo ( ClassUtils.primitiveToWrapper () ), che sarà altrettanto brutto sotto le copertine, ma almeno si può fingere che sia bello.

Puoi chiamare class.isPrimitive () per sapere se è un primitivo o no, tuttavia, non esiste un metodo di boxe per convertire le classi all’interno del JDK. C’è almeno un bug aperto relativo a questo.

Ecco un altro modo se non hai bisogno di codice altamente ottimizzato:

  Class primitive=long.class; Class boxed=Array.get(Array.newInstance(primitive,1),0).getClass(); System.out.println(primitive.getName()); System.out.println(boxed.getName()); 

(Modifica / aggiunta di spiegazioni)

Inizialmente, era per vedere se Java ha un metodo per darti la class wrapper quando viene dato un tipo primitivo. Non ho trovato nessuno.

Quindi, è stato per vedere se è ansible avere Java creare un valore primitivo quando si dà un tipo primitivo (quindi in qualche modo si può ottenere un object da esso). Non ho trovato un modo per farlo.

Ma poi è stato scoperto che si può avere Java creare una matrice di valori primitivi quando viene dato un tipo primitivo. E poi c’è un metodo Java che ti dà un object del tipo di avvolgimento dell’elemento dell’array (che è primitivo). Una volta ottenuto l’object, è ansible ottenere il tipo.

Quindi ecco come funziona tutto:

Il metodo Array.newInstance () crea una matrice di qualsiasi tipo specificato, sia esso primitivo o object. Nel caso dell’object, tutti gli elementi sono di tipo object ma inizializzati su null. Nel caso della primitiva, gli elementi sono di tipo primitivo. Ma l’elemento primitivo variabile / array non può essere nullo, quindi hanno il valore predefinito del tipo primitivo, ad esempio int sarà zero. Quindi nessun elemento sarà nullo. E ora se cerchi di ottenere il valore di un elemento usando Array.get (), Array.get () non ha altra scelta che racchiudere quel valore primitivo in un object, ad es. Int in Integer, perché Array.get () può ‘ t restituire il valore primitivo. Ora hai un object del tipo di boxe (avvolgimento) del tuo tipo primitivo originale. Infine chiamare Object.getClass () ti dà il tipo di boxing (wrapping).

Questo trucco funziona con qualsiasi tipo primitivo che hai in Java oggi e in futuro.

(Idea) Ottieni il nome della class e crea la prima lettera maiuscola, quindi chiama Class.forInstance (className) .newInstance (primitiva). Le eccezioni sono “char” -> Carattere e “int” -> Intero

  Class c=Primitive class object if (c.isPrimitive()) { if (c == char.class) { Object wrapper=new Character(primitive var); } if (c == int.class) { Object wrapper=new Integer(primitive var); } else { String name=c.getName(); try { Class c2=Class.forName("java.lang."+name.substring(0,1).toUpperCase()+name.substring(1,name.length())); Object wrapper=c2.getConstructor(c).newInstance(primitve_var); } catch (ClassNotFoundException ex) { System.out.println("RROR"); } } } 

C’è anche com.sun.beans.finder.PrimitiveWrapperMap # getType (primitiveName). Ma ovviamente usare le classi dal pacchetto “com.sun” non è davvero raccomandato …

 Class toWrapper(Class clazz) { if (!clazz.isPrimitive()) return clazz; if (clazz == Integer.TYPE) return Integer.class; if (clazz == Long.TYPE) return Long.class; if (clazz == Boolean.TYPE) return Boolean.class; if (clazz == Byte.TYPE) return Byte.class; if (clazz == Character.TYPE) return Character.class; if (clazz == Float.TYPE) return Float.class; if (clazz == Double.TYPE) return Double.class; if (clazz == Short.TYPE) return Short.class; if (clazz == Void.TYPE) return Void.class; return clazz; }