Как может быть, что ConcurrentHashMap не имеет метода keySet()?

Я отлаживаю код Java, вызванный из Matlab, и получаю исключение:

Java exception occurred:
java.lang.NoSuchMethodError: java.util.concurrent.ConcurrentHashMap.keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView;

как может быть, что библиотечный класс не имеет библиотечного метода?

ОБНОВЛЕНИЕ

Matlab использует Java7. Код, который я вызываю, был скомпилирован для Java8 и содержит синтаксис

for (Tag t : matrix.keySet()) {

то есть Java8-специфический. Хотя, как утверждается, она должна быть бинарно совместима с Java7, иначе не было бы смысла делать многие компромиссы в Java8.


person Dims    schedule 15.12.2017    source источник
comment
Какую версию Java вы используете? На первый взгляд кажется, что Matlab ожидает версию Java 8, но у вас может быть версия 7.   -  person Zircon    schedule 15.12.2017
comment
но метод keySet() существует для ConcurrentHashMap с Java 6... Я только что проверил 6, 7, 8, и все они имеют метод keySet()... @Zircon   -  person RAZ_Muh_Taz    schedule 15.12.2017
comment
@Raz_Muh_Taz верно, но в Java 7 keySet возвращает Set<K> на свою подпись, а в Java 8 возвращает ConcurrentHashMap.KeySetView<K,V>.   -  person Zircon    schedule 15.12.2017
comment
@Zircon, но разве не утверждается, что код Java8 бинарно совместим с Java7? Здесь мы видим, что я не могу использовать Java8 jar на Java7 машине.   -  person Dims    schedule 15.12.2017
comment
@Dmis Вы можете использовать код Java7 на машине Java8, но не код Java8 на машине Java7. stackoverflow.com/questions/4692626/   -  person Adam Siemion    schedule 15.12.2017
comment
@Dims Что заставляет вас ожидать, что вы можете взять код, скомпилированный для Java 8, и ожидать, что все методы, которые присутствовали в Java 8, будут присутствовать в Java 1.0? Совместимая эволюция работает не так. Вы можете безопасно перемещаться вперед во времени — особое внимание уделяется тому, чтобы убедиться, что это правда, — но не назад.   -  person Brian Goetz    schedule 15.12.2017
comment
@AdamSiemion, тогда почему они не сделали много вещей, например, дженериков во время выполнения? Он был одобрен обратной двоичной совместимостью.   -  person Dims    schedule 15.12.2017
comment
@BrianGoetz используется только для каждого цикла. Он должен быть скомпилирован и работать в предыдущей версии Java, почему бы и нет?   -  person Dims    schedule 15.12.2017
comment
@Dims, вы скомпилировали цикл for с использованием Java 8, поместили в банку, а затем попытались выполнить на машине с Java 7?   -  person Adam Siemion    schedule 16.12.2017
comment
См. мой ответ здесь.   -  person Stuart Marks    schedule 16.12.2017


Ответы (1)


В Java 8 тип возврата ConcurrentHashMap.keySet() был изменен. В Oracle JDK 7:

public Set<K> keySet() {
    Set<K> ks = keySet;
    return (ks != null) ? ks : (keySet = new KeySet());
}

в то время как в Oracle JDK 8:

public KeySetView<K,V> keySet() {
    KeySetView<K,V> ks;
    return (ks = keySet) != null ? ks : (keySet = new KeySetView<K,V>(this, null));
}

public static class KeySetView<K,V> extends CollectionView<K,V,K>
    implements Set<K>, java.io.Serializable {
person Adam Siemion    schedule 15.12.2017
comment
Итак, Java нельзя перенести с 1.7 на 1.8? - person Dims; 15.12.2017
comment
@Dims Это идеально совместимое изменение. KeySetView<K,V> расширяет (является) Set<K>. Это делает реализацию keySet() в ConcurrentHashMap ковариантным переопределением keySet() в Map. И переход от возвращаемого Set<K> к более совершенному KeySetView<K,V> является изменением, совместимым как с двоичным кодом, так и с исходным кодом. Код, написанный или скомпилированный для 7 библиотек, будет работать и для 8. - person Brian Goetz; 15.12.2017
comment
@BrianGoetz какая же это крутость и совместимость, если не работает? Не было смысла использовать ковариантное переопределение или любые другие вещи. Они могли бы просто полностью переименовать метод и полностью изменить как аргументы, так и типы результатов: эффект будет таким же - не работает. - person Dims; 15.12.2017
comment
См. мой ответ здесь. - person Stuart Marks; 16.12.2017
comment
Я обнаружил, что даже если вы напишете Set<Chunk> chunks = wrap.chunksAddPlayer.keySet(); (обратите внимание, что код совместим с Java 7) и скомпилируете с Java 8, во время компиляции он преобразуется в KeySetView, что означает, что вы не сможете использовать его в Java 7. - person Joehot200; 03.01.2019