58

I'm trying to determine the type of a field on an object. I don't know the type of the object when it is passed to me but I need to find fields which are longs. It is easy enough to distinguish the boxed Longs but the primitive long seems more difficult.

I can make sure that the objects passed to me only have Longs, not the primitives, but I'd rather not. So what I have is:

for (Field f : o.getClass().getDeclaredFields()) {
    Class<?> clazz = f.getType();
    if (clazz.equals(Long.class)) {
        // found one -- I don't get here for primitive longs
    }
}

A hacky way, which seems to work, is this:

for (Field f : o.getClass().getDeclaredFields()) {
    Class<?> clazz = f.getType();
    if (clazz.equals(Long.class) ||  clazz.getName().equals("long")) {
        // found one
    }
}

I'd really like a cleaner way to do this if there is one. If there is no better way then I think that requiring the objects I receive to only use Long (not long) would be a better API.

Any ideas?

jpaugh
  • 6,634
  • 4
  • 38
  • 90
macbutch
  • 3,241
  • 2
  • 27
  • 27

4 Answers4

85

You're using the wrong constant to check for Long primitives - use Long.TYPE, each other primitive type can be found with a similarly named constant on the wrapper. eg: Byte.TYPE, Character.TYPE, etc.

Matt
  • 74,352
  • 26
  • 153
  • 180
mP.
  • 18,002
  • 10
  • 71
  • 105
70
o.getClass().getField("fieldName").getType().isPrimitive();
Droo
  • 3,177
  • 4
  • 22
  • 26
  • Yeah I looked at that but I need to know if it is a long primitive not just whether it is a primitive. i.e. match all long primitives but not ints or bytes etc. – macbutch Dec 16 '09 at 12:34
23

You can just use

boolean.class
byte.class
char.class
short.class
int.class
long.class
float.class
double.class
void.class

If you are using reflection, why do you care, why do this check at all. The get/set methods always use objects so you don't need to know if the field is a primitive type (unless you try to set a primitive type to the null value.)

In fact, for the method get() you don't need to know which type it is. You can do

// any number type is fine.
Number n = field.get(object);
long l = n.longValue();

If you are not sure if it is a Number type you can do

Object o = field.get(object); // will always be an Object or null.
if (o instanceof Number) {
     Number n = (Number) o;
     long l = n.longValue();
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Thanks, I didn't know about long.class either. I don't have time to test it but I don't think the rest of your comment applies in my particular case (correct me if I'm wrong. If I do this: Class> returnType = m.getReturnType(); if (returnType.equals(Long.class)) { // do stuff } I don't think it will work - I'd still need to check for long.class or Long.TYPE. If I could just call all get...() methods then I could just check what is returned (but I can't do that). Please, let me know if I've misunderstood (likely...). – macbutch Dec 16 '09 at 12:42
  • I hope you can read that... I forgot the formatting wouldn't come out. :( – macbutch Dec 16 '09 at 12:43
  • try; if (returnType == Long.class || returnType == long.class) – Peter Lawrey Dec 16 '09 at 19:01
  • Coercing all numeric types to `long` is different than fetching only the `long`s – jpaugh Jan 22 '16 at 15:12
  • How do you verify you have a numeric type? `field.getType().isPrimitive()` doesn't work, because it's true for `booleans` as well as numbers. – jpaugh Jan 22 '16 at 15:15
  • @jpaugh do you consider `char` a numeric type. The simplest solution is to have a Set of the classes you consider to be a numeric type. – Peter Lawrey Jan 22 '16 at 18:29
  • Does `longValue` coerce `char` to a `long` correctly? If so, then, "Yes". If not, then, "No". My point was that the abbreviated code you posted doesn't handle all cases; it makes an assumption about the possible types of the field you're working with. It answers the question, but a more general solution would be better, especially for a meta-programming task. – jpaugh Jan 22 '16 at 18:39
  • Of course, it's been 7 years, so the value of changing it is diminished, I suppose. – jpaugh Jan 22 '16 at 18:40
  • @jpaugh I read this as checking for a specific primitive type. The OP doesn't mention checking for a numeric type. – Peter Lawrey Jan 22 '16 at 18:42
  • 2
    As did I. And, I read your post as giving two separate answers, the first (mostly) in English, and the second (mostly) in code. The bottom one does not actually do a check to see if the type matches the specific type the OP needs. If it doesn't, it will fail. (I assume the OP does not know in advance which fields have the type needed.) – jpaugh Jan 22 '16 at 18:44
  • @jpaugh I have clarified what "any number type is fine" means. – Peter Lawrey Jan 22 '16 at 18:50
  • 1
    Thanks for entertaining my nitpick! – jpaugh Jan 22 '16 at 18:54
8
  • To detect fields with long type use long.class or Long.TYPE.

  • To detect fields with Long type use Long.class.

Example:

for (Field f : o.getClass().getDeclaredFields()) {
    Class<?> clazz = f.getType();
    // to detect both Long and long types
    if (Long.class.equals(clazz) || long.class.equals(clazz)) {
        // found one
    }
}

Notice:

Long.TYPE is static Constant member and is equivalent to long.class.

snippet code form Long Class

/**
 * The {@link Class} object that represents the primitive type {@code long}.
 */
@SuppressWarnings("unchecked")
public static final Class<Long> TYPE
        = (Class<Long>) long[].class.getComponentType();

Also check for answer for Difference between Integer.class and Integer.TYPE question

Community
  • 1
  • 1
ahmed hamdy
  • 5,096
  • 1
  • 47
  • 58