Determinare se un object è di tipo primitivo

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