views:

2125

answers:

11

I have an Object[] array, and I am trying to find the ones that are primitives. I've tried to use Class.isPrimitive(), but it seems I'm doing something wrong:

int i = 3;
Object o = i;

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

prints java.lang.Integer, false.

Is there a right way or some alternative?

+14  A: 

The types in an Object[] will never really be primitive - because you've got references! Here the type of i is int whereas the type of the object referenced by o is Integer (due to auto-boxing).

It sounds like you need to find out whether the type is "wrapper for primitive". I don't think there's anything built into the standard libraries for this, but it's easy to code up:

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 HashSet<Class<?>> WRAPPER_TYPES = getWrapperTypes();

    public static boolean isWrapperType(Class<?> clazz)
    {
        return WRAPPER_TYPES.contains(clazz);
    }

    private static HashSet<Class<?>> getWrapperTypes()
    {
        HashSet<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;
    }
}
Jon Skeet
+1 For a home-grown solution. I will delete mine :)
Andrew Hare
I was under the impression that it did work for the primitive wrappers, but it only works for `java.lang.<type>.TYPE` after all, which of course is the primitive itself. It seems I won't be able to avoid checking for each type individually, thanks for the nice solution.
drill3r
+2  A: 

Integer is not a primitive, Class.isPrimitive() is not lying.

Bombe
+4  A: 

Starting in Java 1.5 and up, there is a new feature called auto-boxing. The compiler does this itself. When it sees an opportunity, it converts a primitive type into its appropriate wrapper class.

What is probably happening here is when you declare

Object o = i;

The compiler will compile this statement as saying

Object o = new Integer(i);

This is auto-boxing. This would explain the output you are receiving. This page from the Java 1.5 spec explains auto-boxing more in detail.

Jose Chavez
Not totally true. It doesn't new an Integer, rather it calls Integer.valueOf(int) which does some caching of the Integer instances.
Steve Kuo
Oh that's very true. Thanks for the clear-up!
Jose Chavez
+1  A: 

I think this happens due to auto-boxing.

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

You may implement a utility method that matches these specific boxing classes and gives you if a certain class is 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);
}
bruno conde
+2  A: 
chendral
A: 

As several people have already said, this is due to autoboxing.

You could create a utility method to check whether the object's class is Integer, Double, etc. But there is no way to know whether an object was created by autoboxing a primitive; once it's boxed, it looks just like an object created explicitly.

So unless you know for sure that your array will never contain a wrapper class without autoboxing, there is no real solution.

Michael Myers
+1  A: 

Just so you can see that is is possible for isPrimitive to return true (since you have enough answers showing you why it is false):

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

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

This matters in reflection when a method takes in "int" rather than an "Integer".

This code works:

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

This code failes (cannot find the method):

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

The primitve wrapper types will not respond to this value. This is for class representation of primitives, though aside from reflection I can't think of too many uses for it offhand. So, for example

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

prints "false", but

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

prints "true"

Steve B.
+2  A: 

For those who like terse code.

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

Get ahold of BeanUtils from Spring http://static.springsource.org/spring/docs/3.0.x/javadoc-api/

Probably the apache variation (commons beans) has similar funtionality.

Matthew Young
A: 

commons-lang ClassUtils has wrapperToPrimitive(clazz) method, which will return the primitive correspondence. So you can:

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