Tengo una Object[] matriz, y estoy tratando de encontrar los que son primitivas. He intentado utilizar Class.isPrimitive(), pero parece que estoy haciendo algo mal:

int i = 3;
Object o = i;

System.out.println(o.getClass().getName() + ", " +
                   o.getClass().isPrimitive());

imprime java.lang.Integer, false.

¿Hay una forma correcta o alguna alternativa?

  • En resumen: int.class.isPrimitive() rendimientos true; Integer.class.isPrimitive() rendimientos false.
InformationsquelleAutor drill3r | 2009-04-02

18 Comentarios

  1. 160

    Los tipos en un Object[] nunca realmente ser primitivo – porque tienes referencias! Aquí el tipo de i es int mientras que el tipo del objeto al que hace referencia o es Integer (debido a la auto-boxeo).

    Suena como que usted necesita para averiguar si el tipo es un «contenedor de primitivas». Creo que no hay nada construido en las bibliotecas estándar para esto, pero es fácil de código:

    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<Class<?>> WRAPPER_TYPES = getWrapperTypes();
    
        public static boolean isWrapperType(Class<?> clazz)
        {
            return WRAPPER_TYPES.contains(clazz);
        }
    
        private static Set<Class<?>> getWrapperTypes()
        {
            Set<Class<?>> ret = new HashSet<Class<?>>();
            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;
        }
    }
    • Yo estaba bajo la impresión de que se hizo el trabajo para el primitivo contenedores, pero sólo funciona para java.lang.<type>.TYPE después de todo, que por supuesto es la primitiva de la misma. Parece que no será capaz de evitar la comprobación de cada tipo de forma individual, gracias por la buena solución.
    • Me pregunto si la sobrecarga de uso de HashSet es realmente mejor que un par de instrucciones if.
    • Creo que es más legible, que es la razón por la que me gustaría ir con que en lugar de «si» declaraciones hasta que fue demostró que la sobrecarga de juego es un verdadero cuello de botella.
    • ¿Enum.class ? Debe enumeraciones ser considerados primitivos (aunque técnicamente no lo son)?
    • No, absolutamente no. ¿Por qué sería?
    • Sé que en Java las enumeraciones son más versátiles que los de C# de las enumeraciones. Sin embargo, cuando un Java enum se utiliza para enumerar los valores primitivos que puede ser considerada como una primitiva de contenedor.
    • No estoy de acuerdo. Simplemente no es un tipo primitivo por alguna de los normalmente aceptados definiciones… ¿por qué tratar la sobrecarga de la terminología?
    • Hasta el momento, el contexto en el que yo solía tener una necesidad para determinar si el objeto es una primitiva de contenedor era tal, que las enumeraciones tenía el mismo peso que la real primitivo contenedores. Rara vez veo Java enumeraciones utilizado en una forma más elaborada de la moda de las enumeraciones en C# o C++, aunque son capaces de más.
    • Entonces eso es un contexto muy específico, y debe ser tratada como tal. ¿Autoboxing se aplican a las enumeraciones? No, ya están los tipos de referencia. Son los que no aceptan valores null? No, porque son tipos de referencia… y la lista continúa. Llamando primitivas debilita el significado del término enormemente, y no veo ningún beneficio en ello.
    • Tienes razón…
    • El HashSet permite el acceso en O(1), mientras que una fila de if declaraciones o switch consolidados requiere O(# de contenedores) en el peor de los casos. En la práctica es cuestionable si if declaraciones para el número fijo de 9 contenedores no es tal vez más rápido que el hash basado en el acceso, después de todo.

  2. 75

    commons-lang ClassUtils ha relevantes métodos.

    La nueva versión tiene:

    boolean isPrimitiveOrWrapped = 
        ClassUtils.isPrimitiveOrWrapper(object.getClass());

    Las versiones antiguas han wrapperToPrimitive(clazz) método, que se devolverá el primitivo correspondencia.

    boolean isPrimitiveOrWrapped = 
        clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;
    • Esto no era agregado hasta v3.1, su vínculo se refleja el 2.5 de la API. He corregido.
    • La primavera también ha ClassUtils de la clase, así que si usted ya está usando la Primavera puede ser más conveniente.
  3. 16

    Para aquellos que les gusta lacónico código.

    private static final Set<Class> 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);
    }
    • Por Qué Void.class? ¿Cómo envolver un vacío?
    • devuelve true
    • El vacío es vacío y el único valor válido para un Void es null 😉 es útil para la creación de un Callable<Void> que es Invocable que no devuelve nada.
  4. 8

    Empezando en Java 1.5 y hasta hay una nueva característica llamada auto-boxeo. El compilador hace esto por sí mismo. Cuando ve una oportunidad, lo que convierte a un tipo primitivo en su correspondiente contenedor de la clase.

    Lo que es probablemente lo que sucede aquí es cuando se declara

    Object o = i;

    El compilador compila esta declaración como diciendo

    Object o = Integer.valueOf(i);

    Esto es auto-boxeo. Esto explicaría la salida que está recibiendo. Esta página de Java 1.5 especificación explica auto-boxeo más en detalle.

  5. 5

    Creo que esto ocurre debido a que auto-boxeo.

    int i = 3;
    Object o = i;
    o.getClass().getName(); //prints Integer

    Puede implementar un método de utilidad que coincida con estas clases de boxeo y le da si una determinada clase es primitivo.

    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);
    }
    • Me gusta esta respuesta mejor porque debe ser más rápido que un hash de búsqueda. También hay uno menos HashSet en la memoria (sentado que probablemente no es mucho). Por último, la gente podría optimizar más al pedido de las clases por las que se consideran más frecuentes. Que va a ser diferente en cada aplicación.
    • Usted puede cambiar de manera segura .equals a ==. Las clases son los únicos.
  6. 5

    Usted tiene que tratar con la auto-boxeo de java.

    Veamos el código

    público de la clase de prueba 
    { 
    public static void main(String [ ] args) 
    { 
    int i = 3; 
    Objeto o = i; 
    de retorno; 
    } 
    }

    Usted a la clase test.class y javap -c de la prueba de vamos a inspeccionar el bytecode generado.

    Compilado de "test.java" 
    public class prueba se extiende java.lang.Objeto{ 
    públicos de prueba(); 
    Código: 
    0: aload_0 
    1: invokespecial #1; //Método java/lang/Objeto".":()V 
    4: retorno

    public static void main(java.lang.String[]); Código: 0: iconst_3 1: istore_1 2: iload_1 3: invokestatic #2; //Método java/lang/Entero.valueOf:(I)Ljava/lang/Integer; 6: astore_2 7: regreso

    }

    Como se puede ver el compilador de java añadido

    invokestatic #2; //Método java/lang/Entero.valueOf:(I)Ljava/lang/Integer;

    para crear un nuevo Entero de su int y, a continuación, almacena ese nuevo Objeto en o a través de astore_2

  7. 5
    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;
    }
  8. 3

    Sólo así podrás ver que es posible para isPrimitive a devolver verdadero (ya que usted tiene respuestas suficientes, mostrando por qué es falso):

    public class Main
    {
        public static void main(final String[] argv)
        {
            final Class clazz;
    
            clazz = int.class;
            System.out.println(clazz.isPrimitive());
        }
    }

    Esta materia en la reflexión cuando un método tiene en «int» en lugar de un «Entero».

    Este código funciona:

    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)
        {
        }
    }

    Este código de falla (no se puede encontrar el método):

    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)
        {
        }
    }
  9. 2

    Ya que varias personas ya han dicho, esto es debido a autoboxing.

    Que podría crear un método de utilidad para comprobar si el objeto de la clase es Integer, Double, etc. Pero hay no hay manera de saber si el objeto fue creado por autoboxing una primitiva; una vez en caja, se ve como un objeto creado de forma explícita.

    Así que a menos que usted la certeza de que su matriz, nunca va a contener una clase de contenedor sin autoboxing, no hay ninguna solución real.

  10. 2

    La primitve envoltura de tipos de no responder a este valor. Esto es para la clase de representación de las primitivas, aunque aparte de la reflexión no puedo pensar demasiado muchos usos para ella de improviso. Así, por ejemplo

    System.out.println(Integer.class.isPrimitive());

    imprime «falso», pero

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

    imprime «verdadero»

  11. 2

    Estoy tarde para el espectáculo, pero si estás probando un campo, puede utilizar 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<String> 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));
    }
    }

    La Oracle docs lista de los 8 tipos primitivos.

  12. 1

    Esta es la forma más simple de lo que podía pensar. Las clases de contenedor están presentes sólo en la java.lang paquete. Y aparte de las clases de contenedor, ninguna otra clase en java.lang tiene el nombre del campo de TYPE. Usted podría utilizar para comprobar si una clase es la clase Contenedora o no.

    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;        
    }
    • Que es muy frágil y podría fallar en cualquier momento en el futuro…
    • Estoy de acuerdo. Pero a partir de ahora, es la manera más simple de lo que podía pensar. 🙂
  13. 1

    se podría determinar si un objeto es el tipo de contenedor por debajo de declaraciones:

    ***objClass.isAssignableFrom(Number.class);***

    y también se puede determinar un objeto primitivo mediante la isPrimitive() método

  14. 0
    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

Dejar respuesta

Please enter your comment!
Please enter your name here