Почему в Java не компилируется "array instanceof Iterable"?

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

Этот код компилируется и запускается. Выход:

true
true

Однако этот код не компилируется:

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

Отчет компилятора Eclipse сообщает:

Несовместимые типы условных операндов Object [] и Iterable

Я обнаружил, что массивы можно сравнивать только с интерфейсом Serializable и Cloneable при использовании операции instanceof. Может кто-нибудь сказать мне, почему?

Ответы

Ответ 1

В соответствии с JLS, Java SE 7 edition, § 15.20.2 (Оператор сравнения типов instanceof):

Если преобразование RelationalExpression в ReferenceType будет отклонено как ошибка времени компиляции, то реляционное выражение instanceof также производит ошибка времени компиляции. В такой ситуации результат выражения instanceofникогда не может быть правдой.

И < 15.16 (Cast Exions):

Это ошибка времени компиляции, если тип экземпляра времени компиляции никогда не может быть приведение к типу, указанному оператором литья в соответствии с правилами литья преобразование (§ 5.5).

Наконец, § 5.5.1 (Reference Type Casting):

С учетом ссылочного типа времени слияния S (источник) и ссылочного типа времени компиляции T (target), преобразование каста существует от S до T, если ошибки времени компиляции не происходят из-за следующих правил.

[...]

Если S - тип массива SC [], то есть массив компонентов типа SC:

  • Если T - тип интерфейса, тогда возникает ошибка времени компиляции, если T не является типом java.io.Serializable или тип Cloneable (реализованы только интерфейсы по массивам).

Поэтому Java требует, чтобы ваш тест, чтобы увидеть, является ли массив типом экземпляром java.lang.Iterable, приводит к ошибке времени компиляции.

Если вы хотите попробовать и заставить его работать (всегда возвращать false) в любом случае, вы можете сначала наложить массив на Object следующим образом:

System.out.println((((Object)array) instanceof Iterable));

Ответ 2

Вы смешиваете пригодность объекта для использования в цикле foreach и интерфейс Iterable, которые не реализуются массивами.

Оба массива и Iterable поддерживаются синтаксисом foreach.

Это не означает, что массивы Iterable.

Ответ 3

Я предполагаю, что оба Serializable и Cloneable являются интерфейсами маркеров, где Iterable не является.

Ответ 4

Поскольку java - это статический язык, поэтому компилятор знает, что массив не будет Iterable во время компиляции, компилятор знает, что array instanceof Iterable никогда не может быть правдой, поэтому он запускает ошибку времени компиляции, чтобы предупредить вас.