Android应用程序构建与错误的JDK(?)不知何故

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

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

然后,我在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)

我认为这与以下事实有关:在Java 8中,签名已从返回更改为返回 。keySet()Set<K>KeySetView<K,V>

导致异常的行如下所示:

for (Long id : mSomeMap.keySet())

KeySetView实现 ,它肯定是,所以无论这行被解释为Java 7还是Java 8,我都会认为它会以任何一种方式工作。我对Java基础知识的理解是粗略的 - 这是怎么回事?SetIterable

更新

到目前为止,我的片面理解是这样的:

虽然Android现在支持一些Java 8语言功能,但其API与Java 8并不相同。特别是,Android 的实现返回 a ,而 Java 8 的实现返回 a 。ConcurrentHashMap.keySet()SetConcurrentHashMap.keySet()KeySetView

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

我还没有弄清楚Android Studio如何或为什么使用不兼容的JDK进行构建。在项目结构中,选中了“使用嵌入式JDK(推荐)”,因此我假设Android Studio正在使用与它捆绑在一起的JDK进行构建。

不是解决方案

到目前为止,大多数评论/答案都指出,我可以声明为解决此问题。这是一种解决方法,而不是解决方案。如果潜在的问题是我的应用程序是用错误的JDK构建的,那么可能还有其他实例的方法签名发散,并且由于我无法在大型项目中实时测试100%的代码路径,因此我不能保证在运行时不会抛出更多代码路径。ConcurrentHashMapMapNoSuchMethodErrors


答案 1

我正在使用此解决方法,并且似乎正在工作。

  private final Map<ImageView, Request> mPendingRequests =
            new ConcurrentHashMap<ImageView, Request>();

答案 2

只是把它投给:Map<?, ?>

for (Long id : ((Map< Long, ?>)mSomeMap).keySet())

推荐