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

时间:2017-08-23 16:14:07

标签: java android java-8 concurrenthashmap android-studio-3.0

我最近更新了Android Studio 3的Android项目。我想支持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实现Set,它肯定是Iterable,所以无论这行是解释为Java 7还是Java 8,我都认为它会以任何方式工作。我对Java基础知识的理解是粗略的 - 这里发生了什么?

更新

到目前为止我的不明白是:

虽然Android现在支持某些Java 8语言功能,但其API与Jav​​a 8不同。特别是,Android的ConcurrentHashMap.keySet()实现返回Set,而{8}的Java 8实现}}返回ConcurrentHashMap.keySet()

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

我无法确定Android Studio如何或为何使用不兼容的JDK构建。在项目结构中,选中了“使用嵌入式JDK(推荐)”,因此我假设Android Studio正在使用与其捆绑的JDK构建。

不是解决方案

到目前为止,大多数评论/答案都指出我可以将NoSuchMethodError声明为ConcurrentHashMap来解决这个问题。 这是一种解决方法,而不是解决方案。如果底层问题是我的应用程序是使用错误的JDK构建的,那么可能存在方法签名发散的其他实例,因为我不能在大型项目中对100%的代码路径进行实时测试,我不能保证在运行时不会抛出更多的Map

4 个答案:

答案 0 :(得分:1)

我使用此解决方法似乎正在发挥作用。

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

答案 1 :(得分:0)

您正在使用ConcurrentHashMap的特殊实现

  

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

没有方法<button type="button" class="btn btn btn-danger" data-action="voltar-tela-pedidos" data-scroll-to="pedido-00C407948 "> </button> jQuery(document).on("click", '[data-action="voltar-tela-pedidos"]', function (e) { // i want to know the value of data-scroll-to });

答案 2 :(得分:0)

您可以声明Freeze界面:

ConcurrentMap

然后像这样使用:

ConcurrentMap mSomeMap = new ConcurrentHashMap();

答案 3 :(得分:0)

将其投放到[1, 3].flatMap(x => [x, x + 1]) // > [1, 2, 3, 4]

Map<?, ?>