Android应用程序build立与错误的JDK(?)莫名其妙

我最近更新了Android Studio 3的Android项目。我想支持Java 8语言function,所以添加了以下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>

导致exception的行如下所示:

 for (Long id : mSomeMap.keySet()) 

KeySetView实现Set ,它当然是Iterable ,所以不pipe这行是否被解释为Java 7或Java 8,我都认为它可以工作。 我对Java基础的理解是粗略的 – 这里发生了什么?

更新

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

虽然Android现在支持一些Java 8语言function,但其API与Jav​​a 8不一样。特别是Android的ConcurrentHashMap.keySet()返回一个Set ,而ConcurrentHashMap.keySet()的Java 8实现返回一个KeySetView

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

我并没有仔细研究如何或为什么Android Studio正在构build一个不兼容的JDK。 在项目结构中,选中“使用embedded式JDK(推荐)”,所以我认为Android Studio正在与捆绑在一起的JDK一起构build。

不是解决scheme

到目前为止,大多数评论/回答指出,我可以将ConcurrentHashMap声明为一个Map来解决这个问题。 这是一个解决方法,而不是一个解决scheme。 如果底层的问题是我的应用程序是使用错误的JDK构build的,那么可能会有其他方法签名分歧的情况,由于我无法在大型项目中testing100%的代码path,保证在运行时不会抛出更多的NoSuchMethodErrors

Solutions Collecting From Web of "Android应用程序build立与错误的JDK(?)莫名其妙"

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

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

您正在使用ConcurrentHashMap的特殊实现

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

没有方法keySet()

你可以声明ConcurrentMap接口:

ConcurrentMap mSomeMap = new ConcurrentHashMap();

然后像这样使用:

for (Long id : mSomeMap.keySet())

只是将其投影到Map<?, ?>

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