以某种方式使用错误的 JDK(?)构建 Android 应用程序 [英] Android app building with the wrong JDK(?) somehow

查看:33
本文介绍了以某种方式使用错误的 JDK(?)构建 Android 应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've recently updated my Android project for Android Studio 3. I wanted to support Java 8 language features, so added the following to build.gradle:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

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

I then run my app on an Android 8.0.0 device. At runtime I see

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)

我认为这是因为 keySet() 的签名在 Java 8 中从返回 Set 更改为返回 KeySetView<;K,V>.

I gather this is to do with the fact that the signature of keySet() was changed in Java 8 from returning Set<K> to returning KeySetView<K,V>.

导致异常的行如下所示:

The line that has caused the exception looks like this:

for (Long id : mSomeMap.keySet())

KeySetView 实现了Set,它肯定是Iterable,所以无论这行解释为Java 7 还是Java 8 我都想过无论哪种方式都可以.我对 Java 基础的理解很粗略 - 这里发生了什么?

KeySetView implements Set, it's certainly Iterable, so whether this line is interpreted as Java 7 or Java 8 I'd have thought it would work either way. My understanding of Java fundamentals is sketchy - what's going on here?

更新

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

My flaky understanding so far is this:

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

While Android now supports some Java 8 language features, its API is not identical to Java 8. In particular, Android's implementation of ConcurrentHashMap.keySet() returns a Set, while the Java 8 implementation of ConcurrentHashMap.keySet() returns a KeySetView.

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

Somehow, Android Studio has managed to compile my app with the standard Java 8 JDK and therefore at runtime expects to find a method with the signature KeySetView<K,V> keySet(). However, Android's ConcurrentHashMap does not have a method with this signature, so I get a NoSuchMethodError.

我无法弄清楚 Android Studio 是如何或为何使用不兼容的 JDK 构建的.在项目结构中,使用嵌入式 JDK(推荐)"被选中,因此我假设 Android Studio 是使用捆绑的 JDK 构建的.

I'm no closer to working out how or why Android Studio is building with an incompatible JDK. In Project Structure, 'Use embedded JDK (recommended)' is checked, so I assume Android Studio is building with the JDK that came bundled with it.

不是解决方案

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

Most comments/answers so far have pointed out that I can just declare the ConcurrentHashMap as a Map to get around this. That is a workaround, and not a solution. If the underlying problem is that my app is being built with the wrong JDK, then there may be other instances where method signatures diverge, and since I can't live test 100% of code paths in what is a large project, I can't guarantee that more NoSuchMethodErrors won't be thrown at run time.

推荐答案

just cast to Map:

just cast it to Map<?, ?>:

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

这篇关于以某种方式使用错误的 JDK(?)构建 Android 应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆