@ Бон Эспрессо почти сказал правильный ответ, по моему мнению. И вот мое небольшое дополнение к этому:
Вы должны понимать, что на самом деле делает 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, поэтому выдает ошибку.