189

Is there a preference or behavior difference between using:

if(obj.getClass().isArray()) {}

and

if(obj instanceof Object[]) {}

?

David Citron
  • 43,219
  • 21
  • 62
  • 72

8 Answers8

211

In most cases, you should use the instanceof operator to test whether an object is an array.

Generally, you test an object's type before downcasting to a particular type which is known at compile time. For example, perhaps you wrote some code that can work with a Integer[] or an int[]. You'd want to guard your casts with instanceof:

if (obj instanceof Integer[]) {
    Integer[] array = (Integer[]) obj;
    /* Use the boxed array */
} else if (obj instanceof int[]) {
    int[] array = (int[]) obj;
    /* Use the primitive array */
} else ...

At the JVM level, the instanceof operator translates to a specific "instanceof" byte code, which is optimized in most JVM implementations.

In rarer cases, you might be using reflection to traverse an object graph of unknown types. In cases like this, the isArray() method can be helpful because you don't know the component type at compile time; you might, for example, be implementing some sort of serialization mechanism and be able to pass each component of the array to the same serialization method, regardless of type.

There are two special cases: null references and references to primitive arrays.

A null reference will cause instanceof to result false, while the isArray throws a NullPointerException.

Applied to a primitive array, the instanceof yields false unless the component type on the right-hand operand exactly matches the component type. In contrast, isArray() will return true for any component type.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • 7
    Yeah, but how much difference is it going to make? That sounds like a micro-optimization to me. – Michael Myers Oct 20 '08 at 21:26
  • It depends on the application, but I'd be surprised to find the difference large enough to be worth going out of your way for. But, since it's the conventional approach, you should have some special reason (like support for primitive arrays) to justify using the awkward, sub-optimal reflection. – erickson Oct 20 '08 at 22:00
  • 2
    @Dims If you are asserting that `obj instanceof int[]` yields `false` when you assign an `int[]` to `obj`, you are mistaken. – erickson Feb 13 '13 at 16:58
  • 4
    Sorry I meant that `obj instanceof Object[]` yields `false` if `Object obj = new int[7]`. – Dims Feb 13 '13 at 17:07
  • 3
    Right, in Java, primitive data types are not objects, and don't extend `java.lang.Object`, so that makes sense. But `instanceof` can still be used to test for primitive arrays. – erickson Feb 13 '13 at 17:26
  • If you need to know an object is a general array without having to test every type of primitive array, then getClass().isArray() is a better, less costly approach (in terms of code size) and probably more efficient in terms of operation time too. – ricosrealm Mar 02 '13 at 20:49
  • 4
    -1: In general, since primitive arrays *are* arrays calling `isArray()` should be used. In the very *not general* special case of only having arrays of objects, `instanceof` provides a high performance alternative. – Sam Harwell Apr 23 '13 at 13:34
  • I [cannot generally back the claim](http://stackoverflow.com/a/16171137/521799) that `instanceof` (a thorough check including primitive types) is faster and thus better than `isArray()` – Lukas Eder Apr 23 '13 at 14:18
  • 1
    @280Z28 Couldn't agree less. The question is specifically about `Object[]`. Handling any kind of array is a special case, extremely rare relative to testing for a particular type. Testing for a particular type is done with `instanceof`, not with a special method. Do you wish for `isString()`, `isInputStream()`, `isConnection()`, `isInteger()`, ad infinitum methods on every class? – erickson Apr 23 '13 at 14:33
  • @erickson If you click edit, you'll see I added a more explicit comparison of the two methods inside of a `<-- -->` comment. If you edit the post to include a clearer explanation of the relative advantages of each method (perhaps by removing the `<--` and `-->`), I'll change my -1 to +1. – Sam Harwell Apr 23 '13 at 15:50
34

In the latter case, if obj is null you won't get a NullPointerException but a false.

erickson
  • 265,237
  • 58
  • 395
  • 493
Burkhard
  • 14,596
  • 22
  • 87
  • 108
8

If obj is of type int[] say, then that will have an array Class but not be an instance of Object[]. So what do you want to do with obj. If you are going to cast it, go with instanceof. If you are going to use reflection, then use .getClass().isArray().

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
4

I recently ran into an issue upgrading a Groovy application from JDK 5 to JDK 6. Using isArray() failed in JDK6:

MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...

Changing to instanceof Object[] fixed this.

nalply
  • 26,770
  • 15
  • 78
  • 101
dturanski
  • 1,723
  • 1
  • 13
  • 8
  • This makes no sense. `isArray` is a method of `Class`, not `Type`, so of course `GenericArrayTypeImpl` doesn't have that method. And `getClass` can never return a non-`Class` `Type`, so you (or Groovy??) must have done something wrong to get this, like assuming every `Type` is a `Class`. – kaqqao Dec 08 '17 at 13:06
4

getClass().isArray() is significantly slower on Sun Java 5 or 6 JRE than on IBM.

So much that using clazz.getName().charAt(0) == '[' is faster on Sun JVM.

Jason Plank
  • 2,336
  • 5
  • 31
  • 40
2

If you ever have a choice between a reflective solution and a non-reflective solution, never pick the reflective one (involving Class objects). It's not that it's "Wrong" or anything, but anything involving reflection is generally less obvious and less clear.

Bill K
  • 62,186
  • 18
  • 105
  • 157
2

Java array reflection is for cases where you don't have an instance of the Class available to do "instanceof" on. For example, if you're writing some sort of injection framework, that injects values into a new instance of a class, such as JPA does, then you need to use the isArray() functionality.

I blogged about this earlier in December. http://blog.adamsbros.org/2010/12/08/java-array-reflection/

0

There is no difference in behavior that I can find between the two (other than the obvious null-case). As for which version to prefer, I would go with the second. It is the standard way of doing this in Java.

If it confuses readers of your code (because String[] instanceof Object[] is true), you may want to use the first to be more explicit if code reviewers keep asking about it.

hazzen
  • 17,128
  • 6
  • 41
  • 33