16
Object[] array = new Object[]{};
System.out.println((array instanceof Serializable));//passed
System.out.println((array instanceof Cloneable));//passed

This code compiles and runs. The output is:

true
true

However, this code doesn't compile:

System.out.println((array instanceof Iterable));//not passed

The Eclipse compiler reports:

Incompatible conditional operand types Object[] and Iterable

I found that arrays can only be compared between interfaceSerializable and Cloneable when using operation instanceof. Can someone tell me why?

ohyeahchenzai
  • 314
  • 3
  • 13
  • Related: [Why is an array not assignable to iterable](http://stackoverflow.com/questions/1160081/why-is-an-array-not-assignable-to-iterable) – Greg Kopff Jul 06 '12 at 02:21

4 Answers4

15

According to the JLS, Java SE 7 edition, §15.20.2 (Type Comparison Operator instanceof):

If a cast of the RelationalExpression to the ReferenceType would be rejected as a compile-time error, then the instanceof relational expression likewise produces a compile-time error. In such a situation, the result of the instanceof expression could never be true.

And §15.16 (Cast Expressions) states:

It is a compile-time error if the compile-time type of the operand may never be cast to the type specified by the cast operator according to the rules of casting conversion (§5.5).

Finally, §5.5.1 (Reference Type Casting) states:

Given a compile-time reference type S (source) and a compile-time reference type T (target), a casting conversion exists from S to T if no compile-time errors occur due to the following rules.

[...]

If S is an array type SC[], that is, an array of components of type SC:

  • If T is an interface type, then a compile-time error occurs unless T is the type java.io.Serializable or the type Cloneable (the only interfaces implemented by arrays).

Therefore, Java requires that your test to see if an array type is an instance of java.lang.Iterable results in a compile-time error.

If you want to try and make it work (always return false) anyway, you can cast the array to Object first, like so:

System.out.println((((Object)array) instanceof Iterable));
Jonathan Callen
  • 11,301
  • 2
  • 23
  • 44
  • You could cast to object, but you'd simply end up with "false" every time, as array classes don't implement Iterable. There is special support for arrays in the enhanced for statement, just like there is for iterable. Since array types are not assignment compatible to an Iterable, you get a compile error, much like if you tried to cast a String to a Number. – Matt Jul 06 '12 at 03:04
5

You are confusing suitability of an object for use in a foreach loop, and the Iterable interface, which arrays do not implement.

Both arrays and Iterable are supported with the foreach syntax.

That doesn't mean that arrays are Iterable.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • @GregKopff It's the question asked in the title. – Jeffrey Jul 06 '12 at 02:16
  • 2
    No, the question is not why an array is not iterable; it is why that line is not considered valid Java by the compiler. – Hovercraft Full Of Eels Jul 06 '12 at 02:16
  • Does it have some limits on the relation between left-operand and right-operand when using operation 'instanceof' , I have found that '"123" instanof Iterable' would not passed and if I cast "123" to an Object reference , it will be passed! – ohyeahchenzai Jul 06 '12 at 02:25
  • It's a question of whether the object can possibly match that interface now or in the future. "123" is effectively a final value so it can never be Iterable where an Object could be in some scenarios. – Matt Glover Jul 06 '12 at 02:27
0

I guess its because both Serializable and Cloneable are marker interfaces where as Iterable is not.

Chandra
  • 1,317
  • 11
  • 14
0

Because java is a static language, so the compiler knows an array won't be Iterable at compile time, the compiler knows that array instanceof Iterable could never be true, so it trigger a compile-time error to warn you.

xdazz
  • 158,678
  • 38
  • 247
  • 274