NoSuchMethodError: java.lang.Long.hashCode

У меня есть следующее переопределение метода на hashCode в классе AbstractORM:

var _id = Random().nextLong()

override fun getId() = _id // AbstractORM class implements an interface that defines this method getId()

override fun hashCode() = getId().hashCode()

который неожиданно начал бросать следующее исключение:

FATAL EXCEPTION: main
java.lang.NoSuchMethodError: java.lang.Long.hashCode
   at com.company.ormlite.AbstractORM.hashCode(AbstractORM.kt:271)
   at java.util.HashMap.put(HashMap.java:390)
   at java.util.HashSet.add(HashSet.java:95)
   at kotlin.collections.ArraysKt___ArraysKt.toCollection(_Arrays.kt:6518)
   at kotlin.collections.ArraysKt___ArraysKt.toSet(_Arrays.kt:6853)
   at kotlin.collections.SetsKt__SetsKt.setOf(Sets.kt:32)
   at com.company.android.tna.orm.DataManager.getTables(DataManager.kt:16)
   at com.company.android.tna.orm.DataManager.getTables(DataManager.kt:10)
   at com.company.android.core.utils.AbstractDataManager.create(AbstractDataManager.kt:25)
   at com.company.android.core.utils.AbstractDataManager.start(AbstractDataManager.kt:44)
   at com.company.android.core.utils.AbstractZKApplication.onCreate(AbstractZKApplication.kt:54)
   at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:999)
   at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4151)
   at android.app.ActivityThread.access$1300(ActivityThread.java:130)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1255)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:4745)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
   at dalvik.system.NativeStart.main(Native Method)

Это меня ошеломило по нескольким причинам:

  • Все классы в Java и Kotlin имеют метод hashCode, поскольку он наследуется от Object или Any.
  • Как он не может найти метод, который находится на Android SDK? Если SDK отсутствует, как он работает вообще?
  • При проверке этой строки кода в IntelliJ IDEA она отправляет меня на kotlin.Any.hashCode, а не на java.lang.Long.hashcode.

Любые идеи были бы очень благодарны, спасибо заранее.

Ответ 1

После проверки скомпилированного класса AbstractORM я обнаружил проблему: более новые версии Kotlin генерируют другой код для этой строки

getId().hashCode()

Kotlin 1.1.2 генерирует следующий код:

Long.valueOf(this.getId()).hashCode()

в то время как более новые версии Kotlin генерируют этот другой код:

Long.hashCode(this.getId())

Проблема в том, что этот статический метод Long.hashCode(long) в Android доступен только начиная с API 24 (Android 7.0), в то время как я тестирую на устройстве Android с версией 4.1 (API 16).

Я временно исправляю, вычисляя хеш-код вручную, хотя я открыл проблему здесь.

override fun hashCode() = (getId() xor getId().ushr(32)).toInt()

Как отмечалось в проблеме, переход на цель Java 1.6 для компилятора Kotlin генерирует старый совместимый код.

enter image description here

PS: Я не уверен на 100% в тех версиях Kotlin, пожалуйста, возьмите зерно соли.

Ответ 2

Переопределение функции hashCode(), как предложил m0skit0, сработало для меня. Я реализовал это:

override fun hashCode() : Int = id.toString().hashCode()

Моя настройка компилятора Kotlin в AndroidStudio:

  • инкрементная компиляция включена
  • целевой JVM вер. 1,6

Ответ 3

Я не уверен, как решить вашу проблему, но я попытаюсь объяснить, почему вы получаете это исключение.

В Java 8 новый класс был добавлен в класс Long:

public static int hashCode(long value)

И с тех пор hashCode() метод выглядит следующим образом:

public int hashCode() {
    return hashCode(this.value); // call Long.hashCode() static method
}

Похоже, что у вас есть проблемы с версией Java.