Оператор instanceof в Java для сравнения различных классов - PullRequest
8 голосов
/ 02 февраля 2012

Я пытался понять, как работает оператор instanceof в Java, и столкнулся с очень странной проблемой.

public static void main(String[] args) {
    Map m = new HashMap();
    System.out.println("m instanceof Date: " + (m instanceof Date));
}

Выше возвращается false, как и ожидалось. Тем не менее,

public static void main(String[] args) {
    HashMap m = new HashMap();
    System.out.println("m instanceof Date: " + (m instanceof Date));
}

Это даже не компилируется. Я получаю ошибку

inconvertible types
found   : java.util.HashMap
required : java.util.Date

Что мне здесь не хватает? Я использую IntelliJ Idea 11.

Ответы [ 4 ]

9 голосов
/ 02 февраля 2012

Из спецификации языка Java 3.0, раздел 15.20.2:

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

Поскольку вы не можете скомпилировать приведение от HashMap к Date, вы не можете скомпилироватьinstanceof тест между двумя.

4 голосов
/ 02 февраля 2012

Вы объявляете Map m и используете instanceof, потому что Map - это interface, а новый класс может extends Date implements Map.Другой (не Date) абстрактный класс или класс вызывают ошибку компиляции.

public static void main(String[] args) {
    Map m = new HashMap();
    System.out.println("m instanceof Date: " + (m instanceof Date));
}
2 голосов
/ 02 февраля 2012

@ Бон Эспрессо почти сказал правильный ответ, по моему мнению. И вот мое небольшое дополнение к этому:

Вы должны понимать, что на самом деле делает instanceof, поэтому определение:

instanceof - это двоичный оператор, который проверяет, имеет ли экземпляр определенного типа

Итак, когда вы делаете это:

 Map m = new HashMap();

Во время компиляции m на самом деле является интерфейсом , но фактический тест против instanceof происходит во время выполнения с экземпляром НЕ с интерфейсом , поэтому компилятор не может быть уверен, Экземпляр «позади» m (некоторый класс, который реализует этот интерфейс) на самом деле является классом, который может расширять Date.

Я имею в виду, что у вас может быть класс с такой декларацией:

class MyClass extends Date implements Map{
     .....
}

И тогда вы могли бы сделать это:

 Map myMap = new MyClass();
 (myMap instanceof Date) 

и это было бы совершенно законно, потому что MyClass фактически продлевает Date.

Идея здесь, как вы можете видеть, заключается в том, что если есть наименьшая вероятность того, что проверка с instanceof будет успешной, компилятор не будет жаловаться.

С другой стороны, во втором примере:

    HashMap m = new HashMap();

Вы объявляете фактическую реализацию интерфейса Map или instance . В этом случае компилятор уверен, что HashMap не расширяет Date, поэтому выдает ошибку.

0 голосов
/ 02 февраля 2012

Пожалуйста, обратитесь к спецификации JLS, упомянутой здесь http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.20.2.

Здесь очень хорошо ответили instanceof - несовместимые типы условных операндов

...