以某种方式使用错误的JDK(?)构建Android应用程序

Utt*_*sed 17 java android concurrenthashmap java-8 android-studio-3.0

我最近更新了Android Studio 3的Android项目.我想支持Java 8语言功能,因此在build.gradle中添加了以下内容:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}
Run Code Online (Sandbox Code Playgroud)

然后我在Android 8.0.0设备上运行我的应用程序.在运行时我看到了

java.lang.NoSuchMethodError: No virtual method keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView; in class Ljava/util/concurrent/ConcurrentHashMap; or its super classes (declaration of 'java.util.concurrent.ConcurrentHashMap' appears in /system/framework/core-oj.jar)
Run Code Online (Sandbox Code Playgroud)

我认为这与keySet()Java 8 中的签名从返回Set<K>到返回的事实有关KeySetView<K,V>.

导致异常的行如下所示:

for (Long id : mSomeMap.keySet())
Run Code Online (Sandbox Code Playgroud)

KeySetView实现Set,当然Iterable,所以无论这条线被解释为Java 7还是Java 8,我都认为它可以工作.我对Java基础知识的理解是粗略的 - 这里发生了什么?

更新

到目前为止,我的愚蠢理解是:

虽然Android现在支持一些Java 8语言功能,但它的API与Jav​​a 8并不完全相同.特别是Android的实现ConcurrentHashMap.keySet()返回一个Set,而Java 8的实现则ConcurrentHashMap.keySet()返回一个KeySetView.

不知何故,Android Studio已经设法使用标准的Java 8 JDK编译我的应用程序,因此在运行时期望找到带有签名的方法KeySetView<K,V> keySet().但是,Android ConcurrentHashMap没有这个签名的方法,所以我得到了一个NoSuchMethodError.

我不再研究Android Studio如何或为何使用不兼容的JDK构建.在项目结构中,选中了"使用嵌入式JDK(推荐)",因此我假设Android Studio正在使用与其捆绑的JDK构建.

不是解决方案

到目前为止,大多数评论/答案都指出,我可以宣布这ConcurrentHashMap是一个Map解决这个问题的方法.这是一种解决方法,而不是解决方案.如果潜在的问题是我的应用程序是使用错误的JDK构建的,那么可能存在方法签名分歧的其他实例,并且因为我无法在大型项目中测试100%的代码路径,所以我可以' t保证NoSuchMethodErrors在运行时不会抛出更多.

Tho*_*s.L 0

您正在使用 ConcurrentHashMap 的特殊实现

“java.util.concurrent.ConcurrentHashMap”的声明出现在 /system/framework/core-oj.jar 中

没有方法keySet()

  • 我将该错误解释为 core-oj.jar 没有带有签名“KeySetView&lt;K,V&gt; keySet()”的方法“keySet()”,而不是根本没有任何该名称的方法。*用非常模糊的术语来说*看起来我的应用程序中的类期望找到具有 Java 8 签名的“keySet()”,但找不到它。Android 的 Java 实现只是有点像 Java 8 吗?如果是这样,为什么 Android Studio 构建了这个而不警告我它不会运行? (2认同)