【问题标题】:NoClassDefFoundError when i use lambda to traverse String array当我使用 lambda 遍历字符串数组时出现 NoClassDefFoundError
【发布时间】:2017-05-04 06:00:19
【问题描述】:

使用 lambda 遍历字符串数组时出现跟随错误。

java.lang.NoClassDefFoundError: com.twsz.app.ivybox.alarm.CreateOrUpdateAlarmActivity$$Lambda$1
at com.twsz.app.ivybox.alarm.CreateOrUpdateAlarmActivity.initView(CreateOrUpdateAlarmActivity.java:143)
at com.twsz.app.ivybox.alarm.CreateOrUpdateAlarmActivity.onCreate(CreateOrUpdateAlarmActivity.java:73)

这是我的代码。我知道传统方式遍历字符串数组是可以的,但是为什么在我使用 lambda 时会发生这种情况。

    String[] days = dayOfWeek.split(",");
    Arrays.asList(days).forEach(day->{
        int index = Integer.valueOf(day) -1;
        checkBoxList.get(index).setChecked(true);
    });//where happens NoClassDefFoundError

我的 build.gradle 文件

   android {
        compileSdkVersion 25
        buildToolsVersion "25.0.2"
        defaultConfig {
            applicationId "com.twsz.app.ivybox"
            minSdkVersion 14
            targetSdkVersion 25
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
            vectorDrawables.useSupportLibrary = true
        }

        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }

        dataBinding {
            enabled = true
        }
    }

感谢您的帮助。

【问题讨论】:

  • @SachinGupta String like "1,2,3,4,5,6,7"
  • lamda 需要 java8 或更高版本。据我所知android还不支持java8。
  • @Cyrus 请说明您是如何实现 java 8 功能的,以下任何一种:a) retrolambda b) jack 编译器 c) 新的 android studio 2.4 预览
  • Retrolambda 在内部将 lambda 函数转换为匿名类。目前,您的代码 Arrays.asList(days).forEach(day->{ int index = Integer.valueOf(day) -1; checkBoxList.get(index).setChecked(true); }) 仅受新的 android api 可能 24 及更高版本的支持。

标签: java android lambda


【解决方案1】:
     *
     * @param action The action to be performed for each element
     * @throws NullPointerException if the specified action is null
     * @since 1.8
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

forEach 是默认方法,只有 java8 支持。

Android 不支持所有 Java 8 语言功能。但是,在开发面向 Android 7.0(API 级别 24)的应用时,可以使用以下功能:

默认和静态接口方法
Lambda 表达式(也可用于 API 级别 23 及更低级别)
可重复的注释 方法参考(也适用于 API 级别 23 及更低级别)
类型注释(API 级别 23 及更低级别也可用)

Android 支持默认和静态接口方法,但需要 API 级别 24。更多详情here

defaultConfig {
            applicationId "com.twsz.app.ivybox"
            minSdkVersion 14 // Your minSdkVersion is less than 24
            targetSdkVersion 25
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
            vectorDrawables.useSupportLibrary = true
        }

当您在小于 24 的系统中运行您的应用程序时,您将收到该异常。所以你最好换个方式。传统循环或 Rxjava2。

【讨论】:

    【解决方案2】:

    forEach 方法仅适用于 Android N,您不能使用 SDK 24 之前的 Java 8 中的任何 API。

    即使您使用的是 Retrolambda 或 Jack。

    你需要使用常规的for循环。

    【讨论】:

      【解决方案3】:

      根据 Android,如果你想使用 lambdas,你需要将你的目标 API 设置为低于 23(你的当前设置为 25),然后使用 Jacktool 链。

      根据docs

      Android 不支持所有 Java 8 语言功能。然而 开发应用程序定位时可以使用以下功能 Android 7.0(API 级别 24):

      • 默认和静态接口方法
      • Lambda 表达式(也可用于 API 级别 23 及更低级别)
      • 可重复的注释
      • 方法参考(也可用于 API 级别 23 及更低级别)
      • 类型注释(API 级别 23 及更低级别也可用)

      注意:注意:类型注释信息在编译时可用, 但不是在运行时。此外,该平台支持 API 24 中的 TYPE 和 下面,但不是 ElementType.TYPE_USE 或 ElementType.TYPE_PARAMETER..

      测试 lambda 表达式、方法引用和类型注释 较早版本的 Android,请转到您的 build.gradle 文件,然后设置 compileSdkVersion 和 targetSdkVersion 为 23 或更低。你还是会 需要启用 Jack 工具链才能使用这些 Java 8 功能。

      【讨论】:

        【解决方案4】:

        要使用 Java 8 功能,您需要启用 Jack Toolchain

          defaultConfig {
            ...
            jackOptions {
              enabled true
            }
          }
        

        更多信息请参见documentation

        【讨论】:

        • 它不起作用。我记得数据绑定不能与 Jack 编译器一起工作,但这个错误似乎已修复。
        • 你能指定什么不起作用吗?对于 lambda,您需要 Jack,如果 DataBinding 不适用于 Jack,那么您只能使用 Java 7...
        • 我将 jackOptions 添加到我的 build.gradle 文件中,但在运行我的应用程序时遇到了与 java.lang.NoClassDefFoundError 相同的错误。
        • 尝试做一个干净的构建,我建议手动删除构建目录
        • 我删除了构建目录并重新制作了我的应用程序,但它仍然无法正常工作。
        【解决方案5】:

        来源:https://developer.android.com/guide/platform/j8-jack.html

        如果你想在 android 中使用 lambda,你可以像这样添加到 gradle 选项

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-25
          • 1970-01-01
          • 2020-08-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多