16

I got follow error when I use lambda to traverse String array.

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)

This is my code.I know it's ok for traditional way to traverse the String array ,but why this happen when I use lambda.

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

My build.gradle file

   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
        }
    }

Thanks for any help.

Cyrus
  • 8,995
  • 9
  • 31
  • 58
  • 1
    @SachinGupta String like "1,2,3,4,5,6,7" – Cyrus May 04 '17 at 06:06
  • 3
    check this http://stackoverflow.com/questions/34162074/transforming-lambdas-in-java-8 – Sachin Gupta May 04 '17 at 06:08
  • 1
    lamda require java8 or newer. As far as i know android does not support java8 yet. – k3b May 04 '17 at 07:36
  • @k3b Android has supported some function about java8 .you can find reference [here](https://developer.android.com/studio/preview/features/java8-support.html#migrate) – Cyrus May 04 '17 at 07:53
  • 1
    @ Cyrus Please specify how you are implementing java 8 features, any one of : a) retrolambda b) jack compiler c) new android studio 2.4 preview – Nabin Khatiwada May 15 '17 at 11:34
  • @NabinKhatiwada it's a)retrolambda – Cyrus May 15 '17 at 11:40
  • 1
    Retrolambda internally converts lambda functions to anonymous classes. Currently your code `Arrays.asList(days).forEach(day->{ int index = Integer.valueOf(day) -1; checkBoxList.get(index).setChecked(true); })` is only supported by new android api's probably 24 and higher. – Nabin Khatiwada May 15 '17 at 11:59

5 Answers5

15
     *
     * @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 is default method , it’s only supported by java8.

Android does not support all Java 8 language features. However, the following features are available when developing apps targeting Android 7.0 (API level 24):

Default and static interface methods
Lambda expressions (also available on API level 23 and lower)
Repeatable annotations Method References (also available on API level 23 and lower)
Type Annotations (also available on API level 23 and lower)

Android support default and static interface methods , but it needs API level 24.More details 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
        }

When you run your app in system less than 24, you will get that exception. so you’d better change another way . Traditional loop or Rxjava2.

Mr.ccc
  • 349
  • 1
  • 4
9

forEach method is available only in Android N, you can't use any API from Java 8 before SDK 24.

Even if you are using Retrolambda or Jack.

You need to use regular for loop.

Dimezis
  • 1,541
  • 11
  • 24
8

According to Android, if you want to use lambdas, you need to set your targe API to something lower than 23 (yours is currently set to 25) and then use the Jacktool chain.

Per the docs:

Android does not support all Java 8 language features. However, the following features are available when developing apps targeting Android 7.0 (API level 24):

  • Default and static interface methods
  • Lambda expressions (also available on API level 23 and lower)
  • Repeatable annotations
  • Method References (also available on API level 23 and lower)
  • Type Annotations (also available on API level 23 and lower)

Note: Note: Type annotation information is available at compile time, but not at runtime. Also, the platform supports TYPE in API 24 and below, but not ElementType.TYPE_USE or ElementType.TYPE_PARAMETER..

To test lambda expressions, method references, and type annotations on earlier versions of Android, go to your build.gradle file, and set compileSdkVersion and targetSdkVersion to 23 or lower. You will still need to enable the Jack toolchain to use these Java 8 features.

Community
  • 1
  • 1
BlackHatSamurai
  • 23,275
  • 22
  • 95
  • 156
3

For using Java 8 Features, you need to enable Jack Toolchain

  defaultConfig {
    ...
    jackOptions {
      enabled true
    }
  }

See documentation for more information

Sarvex
  • 763
  • 2
  • 7
  • 19
  • It doesn't work.I remember that Databinding can not work with Jack compiler,but this bug seems like fixed . – Cyrus May 12 '17 at 07:16
  • Can you specify what does not work? For lambda you need Jack, and if DataBinding does not work with Jack, then You have to use Java 7 only... – Sarvex May 12 '17 at 07:25
  • I add jackOptions to my build.gradle file , but I got same error that java.lang.NoClassDefFoundError when run my app. – Cyrus May 12 '17 at 07:32
  • Try doing a clean build, I would recommend t manually deleting the build directory – Sarvex May 12 '17 at 07:50
  • I deleted build directory and remake my app, But it still not work. – Cyrus May 12 '17 at 07:57
  • Then the problem is something else. I would change the code as follows `Arrays.asList(days).forEach(day -> checkBoxList.get(Integer.valueOf(day)).setChecked(true););` – Sarvex May 12 '17 at 08:19
  • Since Android Studio 3.0 (available in Canary channel currently) Jack is deprecated, Java8 features wil be available with Javac and it won't break InstantRun – user1209216 May 19 '17 at 06:34
  • jackOptions deprecated now – Taras Vovkovych Mar 06 '19 at 22:19
2

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

If you want using lambda in android, you add to gradle option like this enter image description here

Zoe
  • 27,060
  • 21
  • 118
  • 148
Park
  • 401
  • 4
  • 10