问题描述
我最近为 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
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
.
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.
导致异常的行如下所示:
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
Iterable
更新
到目前为止我的理解是这样的:
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 featuresConcurrentHashMap.keySet() returns a Set
ConcurrentHashMap.keySet() returns a KeySetView
.
不知何故,Android Studio 已设法使用标准 Java 8 JDK 编译我的应用程序,因此在运行时希望找到具有签名的方法 KeySetView<K.但是,Android 的
ConcurrentHashMap
没有带有此签名的方法,所以我得到一个 NoSuchMethodError
.
SomehowKeySetView<K. HoweverConcurrentHashMap does not have a method with this signatureNoSuchMethodError.
我无法弄清楚 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
不是解决方案
到目前为止,大多数评论/答案都指出我可以将 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 If the underlying problem is that my app is being built with the wrong JDKNoSuchMethodErrors won't be thrown at run time.
推荐答案
just cast to Map
:
just cast it to Map<?:
for (Long id : ((Map< Long
这篇关于以某种方式使用错误的 JDK(?)构建 Android 应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!