Cómo usar funciones del lenguaje Java 8

Android Studio 3.0 y las versiones posteriores admiten todas las funciones del lenguaje Java 7 y un subconjunto de funciones del lenguaje Java 8 que varían según la versión de la plataforma. En esta página, se describen las funciones del lenguaje Java 8 que puedes usar, la manera de configurar correctamente tu proyecto para usarlas y los problemas conocidos que puedes experimentar. Además, mira el siguiente video para obtener una descripción general.

Nota: Cuando se desarrollan apps para Android, el uso de funciones del lenguaje Java 8 es opcional. Puedes mantener los valores de compatibilidad de origen y destino de tu proyecto en Java 7, pero debes usar JDK 8 para la compilación.

Android Studio proporciona compatibilidad integrada para el uso de ciertas funciones del lenguaje Java 8 y bibliotecas de terceros que las usan. Como se muestra en la figura 1, la cadena de herramientas predeterminada implementa las funciones nuevas del lenguaje realizando transformaciones de código de bytes, con el nombre desugar, en el resultado del compilador javac. Ya no se admite Jack y primero debes inhabilitarlo para usar la compatibilidad con Java 8, integrada en la cadena de herramientas predeterminadas.

Figura 1: Compatibilidad con funciones del lenguaje Java 8 mediante transformaciones de código de bytes desugar

Para comenzar a usar las funciones del lenguaje Java 8 compatibles, actualiza el complemento de Android a 3.0.0 (o versiones posteriores). Luego, para cada módulo que use funciones del lenguaje Java 8 (ya sea en su código fuente o a través de dependencias), actualiza Source Compatibility y Target Compatibility a 1.8 en el diálogo Project Structure como se muestra en la figura 2 (haz clic File > Project Structure).

Figura 2: Compatibilidad con funciones del lenguaje Java 8 mediante transformaciones de código de bytes desugar

También puedes configurarlo directamente en el archivo build.gradle correspondiente:

android {
      ...
      // Configure only for each module that uses Java 8
      // language features (either in its source code or
      // through dependencies).
      compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
      }
      // For Kotlin projects
      kotlinOptions {
        jvmTarget = "1.8"
      }
    }
    

Nota: Si Android Studio detecta que tu proyecto usa Jack, Retrolambda o DexGuard, el IDE usará la compatibilidad con Java 8 provista por esas herramientas. Sin embargo, quizás te convenga realizar una migración a la cadena de herramientas predeterminada.

Funciones y API admitidas del lenguaje Java 8

Android Studio no admite todas las funciones del lenguaje Java 8, pero se agregarán más en las versiones futuras del IDE. Según la versión de minSdkVersion que uses, algunas funciones y API ya se encuentran disponibles, como se describe en la siguiente tabla.

Función del lenguaje Java 8 Compatible con minSdkVersion
Expresiones lambda Cualquiera. Ten en cuenta que Android no admite la serialización de expresiones lambda.
Referencias de métodos Cualquiera.
Anotaciones de tipos Cualquiera. Sin embargo, la información de anotaciones de tipos se encuentra disponible en el momento de la compilación pero no en el tiempo de ejecución. Además, la plataforma admite TYPE en el nivel de API 24 y versiones anteriores, pero no ElementType.TYPE_USE ni ElementType.TYPE_PARAMETER.
Métodos de interfaz predeterminados y estáticos Cualquiera.
Repetición de anotaciones Cualquiera.
API del lenguaje Java 8 Compatible con minSdkVersion
java.lang.annotation.Repeatable Nivel de API 24 o versiones posteriores
AnnotatedElement.getAnnotationsByType(Class) Nivel de API 24 o versiones posteriores
java.util.stream Nivel de API 24 o versiones posteriores
java.lang.FunctionalInterface Nivel de API 24 o versiones posteriores
java.lang.reflect.Method.isDefault() Nivel de API 24 o versiones posteriores
java.util.function Nivel de API 24 o versiones posteriores

Además de las API y funciones del lenguaje Java 8, en Android Studio 3.0 y versiones posteriores se extiende la compatibilidad con todos los niveles de API de Android que tengan recursos try.

Por el momento, Desugar no admite MethodHandle.invoke ni MethodHandle.invokeExact. Si tu código fuente o una de las dependencias de tu módulo usan uno de estos métodos, debes especificar minSdkVersion 26 o una versión posterior. De lo contrario, verás el siguiente error:

Dex: Error converting bytecode to dex:
    Cause: signature-polymorphic method called without --min-sdk-version >= 26
    

En algunos casos, es posible que tu módulo no use los métodos invoke ni invokeExact, incluso si forman parte de una dependencia de biblioteca. Por lo tanto, para seguir usando esa biblioteca con minSdkVersion 25 o versiones anteriores, habilita la reducción de código a fin de quitar los métodos sin usar. Si eso no funciona, considera usar una biblioteca alternativa que no emplee los métodos incompatibles.

Cómo migrar a la cadena de herramientas predeterminada

Si Android Studio detecta que tu proyecto usa Jack, Retrolambda o DexGuard, el IDE usará la compatibilidad con Java 8 que proporcionan esas herramientas. Sin embargo, en comparación con la cadena de herramientas predeterminadas, esas herramientas carecen de funcionalidad y compatibilidad. Por lo tanto, sigue las instrucciones de esta sección para realizar la migración a la cadena de herramientas predeterminada de Android Studio.

Cómo migrar desde Jack

La cadena de herramientas Jack dejó de estar disponible, de acuerdo con este anuncio. Si tu proyecto depende de Jack, debes realizar la migración para usar la compatibilidad con Java 8 integrada a la cadena de herramientas predeterminada de Android Studio, que también admite bibliotecas de terceros que usan funciones del lenguaje Java 8, Instant Run y herramientas que dependen de archivos .class intermedios.

Para inhabilitar Jack y cambiar a la cadena de herramientas predeterminada, solo tienes que quitar el bloque jackOptions del archivo build.gradle de tu módulo:

android {
        ...
        defaultConfig {
            ...
            // Remove this block.
            jackOptions {
                enabled true
                ...
            }
        }

        // Keep the following configuration in order to target Java 8.
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
        // For Kotlin projects
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }
    

Cómo migrar desde Retrolambda

En comparación con la cadena de herramientas predeterminada de Android Studio, Retrolambda no admite bibliotecas de terceros que usen funciones del lenguaje Java 8. Para realizar la migración a la cadena de herramientas predeterminada, quita la dependencia Retrolambda del archivo build.gradle de tu nivel de proyecto:

buildscript {
      ...
       dependencies {
          // Remove the following dependency.
          classpath 'me.tatarka:gradle-retrolambda:<version_number>'
       }
    }
    

También quita el complemento de Retrolambda y el bloque retrolambda del archivo build.gradle de cada módulo:

    // Remove the following plugin.
    apply plugin: 'me.tatarka.retrolambda'
    ...
    // Remove this block after migrating useful configurations.
    retrolambda {
        ...
        // If you have arguments for the Java VM you want to keep,
        // move them to your project's gradle.properties file.
        jvmArgs '-Xmx2048m'
    }
    

Cómo inhabilitar la compatibilidad con funciones del lenguaje Java 8

Si experimentas problemas relacionados con la compatibilidad en funciones del lenguaje Java 8, puedes inhabilitarla agregando lo siguiente a tu archivo gradle.properties:

android.enableDesugar=false
    

Para ayudarnos a mejorar la compatibilidad con Java 8, informa un error.