132

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?

drill3r
  • 1,353
  • 2
  • 9
  • 6
  • 15
    In short: `int.class.isPrimitive()` yields `true`; `Integer.class.isPrimitive()` yields `false`. – Patrick Feb 06 '14 at 19:02

18 Answers18

173

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 a "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 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;
    }
}
Hearen
  • 7,420
  • 4
  • 53
  • 63
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I was under the impression that it did work for the primitive wrappers, but it only works for `java.lang..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 Apr 02 '09 at 15:00
  • 3
    I wonder if the overhead of using HashSet is really better than a few if statements. – NateS Feb 24 '11 at 06:43
  • 10
    @NateS: I believe it's more readable, which is why I'd go with that instead of "if" statements until it was *proved* that the overhead of the set is an actual bottleneck. – Jon Skeet Feb 24 '11 at 07:09
  • How about the Enum.class ? Should enums be considered primitive (while technically they are not)? – mark Mar 28 '13 at 16:37
  • I know that Java enums are more versatile than C# enums. However, when a Java enum is used to enumerate primitive values it may be considered as a primitive wrapper. – mark Mar 28 '13 at 16:59
  • @mark: I disagree. It's simply not a primitive type by *any* of the normally accepted definitions... why try to overload the terminology? – Jon Skeet Mar 28 '13 at 17:01
  • So far the context in which I used to have a need to determine if the given object is a primitive wrapper was such, that enums had the same weight as real primitive wrappers. I rarely see Java enums used in a more elaborated fashion than the enums in C# or C++, even though they are capable of more. – mark Mar 28 '13 at 17:26
  • 1
    @mark: Then that's a very specific context, and should be treated as such. Does autoboxing apply to enums? No, they're already reference types. Are they non-nullable? No, because they're reference types... the list goes on. Calling them primitives weakens the meaning of the term hugely, and I see no benefit in it. – Jon Skeet Mar 28 '13 at 17:35
  • 2
    @NateS The `HashSet` allows access in O(1) whereas a row of `if` statements or a `switch` statements requires O(# of wrappers) in the worst case. In practice it's questionable if `if` statements for the fixed number of 9 wrappers isn't maybe faster than hash-based access after all. – Kalle Richter Sep 19 '15 at 13:08
102

commons-lang ClassUtils has relevant methods.

The new version has:

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

The old versions have wrapperToPrimitive(clazz) method, which will return the primitive correspondence.

boolean isPrimitiveOrWrapped = 
    clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;
Hearen
  • 7,420
  • 4
  • 53
  • 63
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 2
    This wasn't [added until v3.1](https://issues.apache.org/jira/browse/LANG-756), your link reflected the 2.5 API. I've corrected it. – javamonkey79 Sep 13 '12 at 06:40
  • 10
    Spring also has [ClassUtils](http://docs.spring.io/spring/docs/3.1.4.RELEASE/javadoc-api/org/springframework/util/ClassUtils.html#isPrimitiveOrWrapper(java.lang.Class)) class, so if you are already using Spring it can be more convenient. – Sergey Feb 18 '14 at 15:41
  • @Bozho ClassUtils.isPrimitiveOrWrapper is giving false for java.lang.String – Joy Oct 14 '20 at 14:16
  • @Joy, a String is neither a primitive nor a wrapped primitive, see [here](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html) for a overview of all the primitive data types. You could add `object instanceof String` to your code if you need it of course! – Jacob van Lingen Aug 17 '21 at 15:15
27

Google's Guava library has a Primitives utility that check if a class is a wrapper type for a primitive: Primitives.isWrapperType(class).

Class.isPrimitive() works for primitives

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Andrejs
  • 26,885
  • 12
  • 107
  • 96
20

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
  • 525,659
  • 79
  • 751
  • 1,130
9

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 = Integer.valueOf(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.

Zordid
  • 10,451
  • 11
  • 42
  • 58
Jose
  • 1,616
  • 4
  • 26
  • 38
  • 6
    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 Apr 02 '09 at 15:48
  • 1
    @SteveKuo `Integer.valueOf(int)` itself only returns cached value when the argument is "a byte" (read: between -128, 127, both inclusive). Otherwise it calls `new Integer(int)`. See: http://developer.classpath.org/doc/java/lang/Integer-source.html#line.305, http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/Integer.java#l829 – Dragas Feb 28 '19 at 12:18
7

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
  • 47,767
  • 15
  • 98
  • 117
  • I like this answer best because it should be faster than a hash lookup. There's also one less HashSet in memory (granted that probably isn't much). Lastly, folks could optimize this further by ordering the classes by which ones are perceived to be more frequent. That'll be different in every application. – bmauter Jan 15 '14 at 19:24
  • 6
    You can safely change `.equals` to `==`. Classes are singletons. – Boann Jul 30 '14 at 14:38
6
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;
}
user3395079
  • 63
  • 1
  • 4
6

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

Bombe
  • 81,643
  • 20
  • 123
  • 127
5

You have to deal with the auto-boxing of java.
Let's take the code

public class test
{
    public static void main(String [ ] args)
    {
        int i = 3;
        Object o = i;
        return;
    }
}
You get the class test.class and javap -c test let's you inspect the generated bytecode.
Compiled from "test.java"
public class test extends java.lang.Object{
public test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method 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; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 6: astore_2 7: return

}

As you can see the java compiler added
invokestatic    #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
to create a new Integer from your int and then stores that new Object in o via astore_2
chendral
  • 694
  • 1
  • 6
  • 17
3

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 fails (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
  • 60,850
  • 18
  • 118
  • 163
2

I'm late to the show, but if you're testing a field, you can use 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));
    }
}

The Oracle docs list the 8 primitive types.

whistling_marmot
  • 3,561
  • 3
  • 25
  • 39
2

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
  • 188,989
  • 46
  • 291
  • 292
2

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.
  • 55,454
  • 12
  • 93
  • 132
1

This is the simplest way I could think of. The wrapper classes are present only in java.lang package. And apart from the wrapper classes, no other class in java.lang has field named TYPE. You could use that to check whether a class is Wrapper class or not.

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;        
}
Rahul Bobhate
  • 4,892
  • 3
  • 25
  • 48
1

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 functionality.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Matthew Campbell
  • 1,864
  • 3
  • 24
  • 51
1

you could determine if an object is wrapper type by beneath statements:

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

and you could also determine a primitive object by using the isPrimitive() method

airblock
  • 11
  • 1
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
Arham
  • 2,072
  • 2
  • 18
  • 30
0

For users of javapoet, there's also this way:

private boolean isBoxedPrimitive(Class<?> type) {
    return TypeName.get(type).isBoxedPrimitive();
}