Android
Java на Android
Поиск…
Вступление
Android поддерживает все языковые функции Java 7 и набор функций языка Java 8, которые различаются по версии платформы. На этой странице описываются новые возможности языка, которые вы можете использовать, как правильно настроить проект для их использования и любые известные проблемы, с которыми вы можете столкнуться.
Java 8 имеет подмножество с Retrolambda
Retrolambda позволяет запускать код Java 8 с помощью лямбда-выражений, ссылок на методы и операторов try-with-resources на Java 7, 6 или 5. Это делается путем преобразования вашего скомпилированного байт-кода Java 8, чтобы он мог работать в более старой среде выполнения Java.
Особенности языка бэкпорта:
Лямбда-выражения передаются обратно, превращая их в анонимные внутренние классы. Это включает в себя оптимизацию использования экземпляра singleton для выражений лямбда без учета состояния, чтобы избежать повторного распределения объектов. Ссылки на методы - это, по сути, только синтаксический сахар для лямбда-выражений, и они обращаются таким же образом.
Операторы Try-with-resources передаются обратно, удаляя вызовы
Throwable.addSuppressed
если целевая версия байт-кода находится ниже Java 7. Если вы хотите, чтобы исключенные исключения были записаны вместо проглатывания, создайте запрос функции, и мы сделаем это настраивается.Objects.requireNonNull
вызовы заменяются вызовамиObject.getClass
если целевая версия байт-кода находится ниже Java 7. Синтетические проверки на null, сгенерированные JDK 9, используютObjects.requireNonNull
, тогда как в предыдущих версиях JDK использовалсяObject.getClass
.Дополнительно также:
Способы по умолчанию возвращаются путем копирования методов по умолчанию в класс сопутствующего класса (имя интерфейса + «$») в качестве статических методов, заменяя методы по умолчанию в интерфейсе абстрактными методами и добавляя необходимые реализации методов ко всем классам, реализующим этот интерфейс ,
Статические методы на интерфейсах возвращаются путем перемещения статических методов в класс компаньона (имя интерфейса + «$») и путем изменения всех вызовов методов для вызова нового расположения метода.
Известные ограничения:
Не поддерживает API-интерфейсы Java 8
Backporting методы по умолчанию и статические методы на интерфейсах требуют, чтобы все backported интерфейсы и все классы, которые их реализовали, или вызывали их статические методы для резервного копирования вместе с одним выполнением Retrolambda. Другими словами, вы всегда должны делать чистую сборку. Кроме того, методы backporting default не будут работать через границы модулей или зависимостей.
Может разорваться, если будущая сборка JDK 8 перестанет генерировать новый класс для каждого
invokedynamic
вызова. Retrolambda работает так, что он захватывает байт-код, которыйjava.lang.invoke.LambdaMetafactory
генерируется динамически, поэтому оптимизация этого механизма может сломать Retrolambda.
Retrolambda gradle plugin автоматически создаст ваш проект Android с Retrolambda. Последнюю версию можно найти на странице выпусков .
Использование:
- Загрузите и установите jdk8
- Добавьте в свой
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'me.tatarka:gradle-retrolambda:<latest version>'
}
}
// Required because retrolambda is on maven central
repositories {
mavenCentral()
}
apply plugin: 'com.android.application' //or apply plugin: 'java'
apply plugin: 'me.tatarka.retrolambda'
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
Известные вопросы:
Lint терпит неудачу в java-файлах, которые имеют lambdas. Волокна Android не понимает синтаксис java 8 и терпит неудачу молча или громко. В настоящее время существует экспериментальная версия, которая устраняет проблему.
Использование служб Google Play приводит к сбою Retrolambda. Версия 5.0.77 содержит байт-код, который несовместим с Retrolambda. Это должно быть исправлено в новых версиях игровых сервисов, если вы можете их обновить, это должно быть предпочтительным решением. Чтобы обойти эту проблему, вы можете использовать более раннюю версию, например 4.4.52, или добавить
-noverify
в jvm args.
retrolambda {
jvmArgs '-noverify'
}