Ho una matrice Object[]
e sto cercando di trovare quelli che sono primitivi. Ho provato a utilizzare Class.isPrimitive()
, ma sembra che stia facendo qualcosa di sbagliato:
int i = 3; Object o = i; System.out.println(o.getClass().getName() + ", " + o.getClass().isPrimitive());
stampa java.lang.Integer, false
.
C’è un modo giusto o qualche alternativa?
I tipi in un Object[]
non saranno mai veramente primitivi – perché hai riferimenti! Qui il tipo di i
è int
mentre il tipo di object a cui fa riferimento o
è Integer
(a causa del box automatico).
Sembra che tu abbia bisogno di scoprire se il tipo è “wrapper for primitive”. Non penso che ci sia qualcosa di incorporato nelle librerie standard per questo, ma è facile da codificare:
import java.util.*; public class Test { public static void main(String[] args) { System.out.println(isWrapperType(String.class)); System.out.println(isWrapperType(Integer.class)); } private static final Set> WRAPPER_TYPES = getWrapperTypes(); public static boolean isWrapperType(Class> clazz) { return WRAPPER_TYPES.contains(clazz); } private static Set> getWrapperTypes() { Set> ret = new HashSet>(); ret.add(Boolean.class); ret.add(Character.class); ret.add(Byte.class); ret.add(Short.class); ret.add(Integer.class); ret.add(Long.class); ret.add(Float.class); ret.add(Double.class); ret.add(Void.class); return ret; } }
ClassUtils
commons-lang ha metodi pertinenti. La nuova versione ha:
boolean isPrimitiveOrWrapped = ClassUtils.isPrimitiveOrWrapper(object.getClass());
Le vecchie versioni hanno wrapperToPrimitive(clazz)
metodo wrapperToPrimitive(clazz)
, che restituirà la corrispondenza primitiva . Quindi puoi fare:
boolean isPrimitiveOrWrapped = clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;
La libreria Guava di Google ha un’utilità Primitives che controlla se una class è un tipo di wrapper per una primitiva: http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/primitives/Primitives.html
Primitives.isWrapperType(class)
Class.isPrimitive () funziona per i primitivi
Per coloro a cui piace il codice terse.
private static final Set WRAPPER_TYPES = new HashSet(Arrays.asList( Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class)); public static boolean isWrapperType(Class clazz) { return WRAPPER_TYPES.contains(clazz); }
A partire da Java 1.5 e versioni successive, c’è una nuova funzionalità chiamata auto-boxing. Il compilatore lo fa da sé. Quando vede un’opportunità, converte un tipo primitivo nella sua class wrapper appropriata.
Quello che probabilmente sta succedendo qui è quando dichiari
Object o = i;
Il compilatore compilerà questa dichiarazione come dicendo
Object o = Integer.valueOf(i);
Questo è il box automatico. Questo spiegherebbe l’output che stai ricevendo. Questa pagina dalle specifiche Java 1.5 spiega il box automatico in modo più dettagliato.
Integer
non è un primitivo, Class.isPrimitive()
non sta mentendo.
Penso che questo accada a causa dell’auto-boxing .
int i = 3; Object o = i; o.getClass().getName(); // prints Integer
È ansible implementare un metodo di utilità che corrisponda a queste classi di boxe specifiche e fornisce se una certa class è primitiva.
public static boolean isWrapperType(Class> clazz) { return clazz.equals(Boolean.class) || clazz.equals(Integer.class) || clazz.equals(Character.class) || clazz.equals(Byte.class) || clazz.equals(Short.class) || clazz.equals(Double.class) || clazz.equals(Long.class) || clazz.equals(Float.class); }
Devi occuparti dell’auto-boxing di java.
Prendiamo il codice
test di class pubblica { public static void main (String [] args) { int i = 3; Oggetto o = i; ritorno; } }
Ottieni la class test.class e javap -c test ti lascia ispezionare il codice byte generato.
Compilato da "test.java" test di class pubblica estende java.lang.Object { test pubblico (); Codice: 0: aload_0 1: invokespecial # 1; // Metodo java / lang / Object. "" :() V 4: ritorno
public static void main (java.lang.String []);
Codice:
0: iconst_3
1: istore_1
2: iload_1
3: invokestatic # 2; // Metodo java / lang / Integer.valueOf: (I) Ljava / lang / Integer;
6: astore_2
7: ritorno
} Come puoi vedere il compilatore java aggiunto
invokestatic # 2; // Metodo java / lang / Integer.valueOf: (I) Ljava / lang / Integer;
per creare un nuovo intero da int e quindi memorizza il nuovo object in o tramite astore_2
public static boolean isValidType(Class> retType) { if (retType.isPrimitive() && retType != void.class) return true; if (Number.class.isAssignableFrom(retType)) return true; if (AbstractCode.class.isAssignableFrom(retType)) return true; if (Boolean.class == retType) return true; if (Character.class == retType) return true; if (String.class == retType) return true; if (Date.class.isAssignableFrom(retType)) return true; if (byte[].class.isAssignableFrom(retType)) return true; if (Enum.class.isAssignableFrom(retType)) return true; return false; }
Solo così puoi vedere che è ansible che isPrimitive restituisca true (dal momento che hai abbastanza risposte che ti mostrano perché è falso):
public class Main { public static void main(final String[] argv) { final Class clazz; clazz = int.class; System.out.println(clazz.isPrimitive()); } }
Questo è importante quando un metodo accetta “int” piuttosto che un “Integer”.
Questo codice funziona:
import java.lang.reflect.Method; public class Main { public static void main(final String[] argv) throws Exception { final Method method; method = Main.class.getDeclaredMethod("foo", int.class); } public static void foo(final int x) { } }
Questo codice ha esito negativo (imansible trovare il metodo):
import java.lang.reflect.Method; public class Main { public static void main(final String[] argv) throws Exception { final Method method; method = Main.class.getDeclaredMethod("foo", Integer.class); } public static void foo(final int x) { } }
Come molte persone hanno già detto, questo è dovuto al autoboxing .
È ansible creare un metodo di utilità per verificare se la class dell’object è Integer
, Double
, ecc. Ma non c’è modo di sapere se un object è stato creato da autoboxing di una primitiva ; una volta che è in scatola, sembra proprio come un object creato esplicitamente.
Quindi, a meno che tu non sappia per certo che la tua matrice non conterrà mai una class wrapper senza autoboxing, non esiste una soluzione reale.
I tipi di wrapper primitve non rispondono a questo valore. Questo è per la rappresentazione di class dei primitivi, sebbene a prescindere dalla riflessione non riesco a pensare a troppi usi per lui a rovescio. Quindi, per esempio
System.out.println(Integer.class.isPrimitive());
stampa “falso”, ma
public static void main (String args[]) throws Exception { Method m = Junk.class.getMethod( "a",null); System.out.println( m.getReturnType().isPrimitive()); } public static int a() { return 1; }
stampa “vero”
Sono in ritardo per lo spettacolo, ma se stai testando un campo, puoi usare getGenericType
:
import static org.junit.Assert.*; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import org.junit.Test; public class PrimitiveVsObjectTest { private static final Collection PRIMITIVE_TYPES = new HashSet<>(Arrays.asList("byte", "short", "int", "long", "float", "double", "boolean", "char")); private static boolean isPrimitive(Type type) { return PRIMITIVE_TYPES.contains(type.getTypeName()); } public int i1 = 34; public Integer i2 = 34; @Test public void primitive_type() throws NoSuchFieldException, SecurityException { Field i1Field = PrimitiveVsObjectTest.class.getField("i1"); Type genericType1 = i1Field.getGenericType(); assertEquals("int", genericType1.getTypeName()); assertNotEquals("java.lang.Integer", genericType1.getTypeName()); assertTrue(isPrimitive(genericType1)); } @Test public void object_type() throws NoSuchFieldException, SecurityException { Field i2Field = PrimitiveVsObjectTest.class.getField("i2"); Type genericType2 = i2Field.getGenericType(); assertEquals("java.lang.Integer", genericType2.getTypeName()); assertNotEquals("int", genericType2.getTypeName()); assertFalse(isPrimitive(genericType2)); } }
I documenti Oracle elencano gli 8 tipi primitivi.
Questo è il modo più semplice che potessi pensare. Le classi wrapper sono presenti solo nel pacchetto java.lang
. E a parte le classi wrapper, nessun’altra class in java.lang
ha un campo chiamato TYPE
. Potresti usarlo per verificare se una class è o meno una class Wrapper.
public static boolean isBoxingClass(Class> clazz) { String pack = clazz.getPackage().getName(); if(!"java.lang".equals(pack)) return false; try { clazz.getField("TYPE"); } catch (NoSuchFieldException e) { return false; } return true; }
Approfitta di BeanUtils da Spring http://static.springsource.org/spring/docs/3.0.x/javadoc-api/
Probabilmente la variazione di Apache (fagioli comuni) ha una funzionalità simile.
è ansible determinare se un object è un tipo di wrapper di sotto le istruzioni:
***objClass.isAssignableFrom(Number.class);***
e potresti anche determinare un object primitivo usando il metodo isPrimitive ()
public class CheckPrimitve { public static void main(String[] args) { int i = 3; Object o = i; System.out.println(o.getClass().getSimpleName().equals("Integer")); Field[] fields = o.getClass().getFields(); for(Field field:fields) { System.out.println(field.getType()); } } } Output: true int int class java.lang.Class int