2015-03-17 2 views
0

Я работаю над веб-приложением на базе Java и внезапно обнаружил поведение, которое я не могу понять на данный момент.Java/Eclipse: возврат в список casted Map.values ​​()

Скажем, у меня следующий код:

...snip... 
Map<Integer, Foo> map = new HashMap<Integer, Foo>(); 
...snip... 

public List<Foo> getFoos() { 
    return (List<Foo>)map.values(); 
} 

Я знаю, что вам нужно создавать новый список, как новый ArrayList(), например, но мне интересно, почему затмение не дает мне предупреждение.

Только при запуске кода I (будет) получить ClassCastException. Я совершенно уверен, что это не ошибка eclipse, так как у компилятора также нет проблем с этим кодом, но кто-нибудь может объяснить мне, почему вы всегда получаете ошибку при запуске этого кода, но IDE и компилятор не жалуются?

+0

Компилятор не жалуется, потому что ClassCastException является неконтролируемым исключением. он не проверяется во время компиляции – cjcroix

+0

Анализ IntelliJ's -> Inspect Code даст вам предупреждение по этому коду, но по причинам, указанным ниже, это действует до времени выполнения. –

ответ

1

Согласно javadoc, Map.values() возвращает Collection<V>, что означает, что нет гарантии, что это будет List. Это зависит от внутренней реализации конкретной карты (в вашем случае реализация метода HashMap#values() возвращает реализацию интерфейса AbstractCollection, называемого Values, и это не является a List).

Лучше измените тип возвращаемого метода на Collection<Foo> и удалите отливку.

5

И IDE, и компилятор проверяют только на синтаксическом уровне. И на синтаксическом уровне все в порядке. Тип результата getFoos() имеет допустимый тип List из-за броска, а все остальное в порядке. На самом деле это ошибка в семантике. На семантическом уровне вы пытаетесь передать результат map.values(), который фактически вернет экземпляр внутреннего типа HashMap, который выводится непосредственно из AbstractCollection, в List. Поскольку это недопустимое действие (список не является супертипом результата map.values()), java будет вызывать исключение ClassCastException во время выполнения.

0

Map.values() предполагается возвращение Collection. Поскольку все List s :Collection s, реализация Map.values может вернуть List, а литье будет верным. Во время компиляции невозможно доказать, что значения карты Collection будут List, но также не могут опровергнуть его, поэтому компилятор разрешает код, но вставляет проверку времени выполнения.