web-dev-qa-db-fra.com

Déterminer si un objet est de type primitif

J'ai un tableau Object[] Et j'essaie de trouver ceux qui sont des primitives. J'ai essayé d'utiliser Class.isPrimitive(), mais il semble que je fasse quelque chose de mal:

int i = 3;
Object o = i;

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

imprime Java.lang.Integer, false.

Y a-t-il un bon moyen ou une alternative?

103
drill3r

Les types dans un Object[] _ ne sera jamais vraiment être primitif - car vous avez des références! Ici, le type de i est int alors que le type de l'objet référencé par o est Integer (en raison de la boxe automatique).

Il semble que vous ayez besoin de savoir si le type est un "wrapper for primitive". Je ne pense pas qu'il y ait quoi que ce soit construit dans les bibliothèques standard, mais c'est facile à coder:

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;
    }
}
158
Jon Skeet

commons-langClassUtils a des méthodes pertinentes .

La nouvelle version a:

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

Les anciennes versions ont la méthode wrapperToPrimitive(clazz), qui renverra la correspondance primitive .

boolean isPrimitiveOrWrapped = 
    clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;
73
Bozho

La bibliothèque Google de Google a un utilitaire Primitives qui vérifie si une classe est un type d’emballage pour une primitive: http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/primitives/ Primitives.html

Primitives.isWrapperType(class)

Class.isPrimitive () fonctionne pour les primitives

24
Andrejs

Pour ceux qui aiment le code laconique.

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);
}
16
Peter Lawrey

À partir de Java 1.5 et supérieur, il existe une nouvelle fonctionnalité appelée box automatique. Le compilateur le fait lui-même. Lorsqu'il voit une opportunité, il convertit un type primitif en classe de wrapper appropriée.

Ce qui se passe probablement ici est lorsque vous déclarez

Object o = i;

Le compilateur compilera cette déclaration en disant

Object o = Integer.valueOf(i);

Ceci est la boxe automatique. Cela expliquerait le résultat que vous recevez. Cette page de la Java 1.5 explique la boxe automatique plus en détail.

8
Jose Chavez

Integer n'est pas une primitive, Class.isPrimitive() ne ment pas.

6
Bombe
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;
}
5
user3395079

Je pense que cela se produit en raison de boxe automatique.

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

Vous pouvez implémenter une méthode utilitaire qui correspond à ces classes de boxe spécifiques et vous indique si une classe est primitive.

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);
}
5
bruno conde

Vous devez faire face à la boxe automatique de Java.
Prenons le code

test de classe publique 
 {
 public static void main (String [] args) 
 {
 int i = 3; 
 Objet o = i; 
        revenir;
    }
}
javap -c test
Compilé à partir de "test.Java" 
 Test de classe publique étend Java.lang.Object {
 Test public (); 
 Code: 
 0: aload_0 
 1: invokespecial # 1; // Méthode Java/lang/Object. "" :() V 
 4: return 
 

public static void main (Java.lang.String []); Code: 0: iconst_3 1: istore_1 2: iload_1 3: invokestatic # 2; // Méthode Java/lang/Integer.valueOf: (I) Ljava/lang/Integer; 6: astore_2 7: return
}
invokestatic # 2; // Méthode Java/lang/Integer.valueOf: (I) Ljava/lang/Integer;
ce nouvel objet
5
chendral

Pour que vous puissiez voir qu'il est possible de renvoyer true avec isPrimitive (puisque vous avez suffisamment de réponses pour vous expliquer pourquoi il est faux):

public class Main
{
    public static void main(final String[] argv)
    {
        final Class clazz;

        clazz = int.class;
        System.out.println(clazz.isPrimitive());
    }
}

Ceci est important dans la réflexion lorsqu'une méthode utilise "int" plutôt qu'un "Integer".

Ce code fonctionne:

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

Ce code échoue (impossible de trouver la méthode):

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

Comme plusieurs personnes l'ont déjà dit, cela est dû à autoboxing .

Vous pouvez créer une méthode utilitaire pour vérifier si la classe de l'objet est Integer, Double, etc. Mais il y a aucun moyen de savoir si un objet a été créé en sélectionnant automatiquement une primitive ; une fois mis en boîte, il ressemble à un objet créé explicitement.

Donc, à moins que vous ne sachiez avec certitude que votre tableau ne contiendra jamais de classe wrapper sans auto-sélection, il n'y a pas de vraie solution.

2
Michael Myers

Je suis en retard pour le spectacle, mais si vous testez un champ, vous pouvez utiliser 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));
    }
}

Les docs Oracle listent les 8 types primitifs.

2
whistling_marmot

Les types de wrapper primitve ne répondront pas à cette valeur. Ceci est destiné à la représentation en classe des primitifs, bien que, mis à part la réflexion, je ne puisse pas penser à de nombreuses utilisations. Donc, par exemple

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

affiche "faux", mais

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 "vrai"

2
Steve B.

Découvrez BeanUtils à partir du printemps http://static.springsource.org/spring/docs/3.0.x/javadoc-api/

La variante Apache (beans communs) a probablement des fonctionnalités similaires.

1
Matthew Campbell

C'est le moyen le plus simple auquel je puisse penser. Les classes wrapper sont présentes uniquement dans Java.lang paquet. Et en dehors des classes wrapper, aucune autre classe dans Java.lang a un champ nommé TYPE. Vous pouvez l'utiliser pour vérifier si une classe est une classe Wrapper ou non.

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;        
}
1
Rahul Bobhate

vous pouvez déterminer si un objet est de type wrapper à l'aide des instructions suivantes:

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

et vous pouvez également déterminer un objet primitif à l'aide de la méthode isPrimitive ()

1
airblock

Dix ans et cette question est toujours d'actualité, du moins pour moi ... Quel est le lien entre "isPrimitive" s'il ne fonctionne pas avec des instances de primitives? Je sais que la classe 'int.class' est primitive, je n'ai donc pas besoin de demander ceci ... Eh bien, j'ai écrit ceci:

import Java.lang.reflect.*;
class Test{
  public static void main(String[] args) throws Exception{
    char x=3; boolean b=true; int i=2;
    Object o= i;
    Object name =o.getClass().getField("TYPE").get(o);
    System.out.println(""+name);
  }
}

Cela retournera une chaîne comme "int", "char", "boolean", etc. Tous les huit primitifs ont une classe de wrapper qui a le champ "TYPE" qui contient ces valeurs. Le type vide le fait aussi.

Autre moyen, utilisation pratique:

import Java.util.*;
import Java.lang.reflect.*;
class Test{
  static void print(Object O){System.out.println(O);}
  public static void main(String[] args) throws Exception{
    List list2 = new ArrayList<Object>(List.of("Word",2,3.0f,4.0,(char)65, a)); //where a= any user class instance. 
//And see like this list simulates a Tuple like in Pyhton, another lack i see in Java.
//But indeed, this kind of List<Object> is still better then a immutable Tuple. 
//And this was another of my doubts (tuples), and of other's people, as i've seen in my searchs at web.
    ver(list2);

  }
  static void ver(List lis){
    List prims = new ArrayList<String>(List.of("Boolean","Character","Byte","Double","Float","Integer","Long","Short"));
    for(Object o: lis){
      String s=o.getClass().getSimpleName();
      print((prims.contains(s)?"Yes":"No"));
    }
  }

sortie: Non Oui Oui Oui Oui Non

0
Carlos Leandro
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
0
Arham