Android
Java na Androida
Szukaj…
Wprowadzenie
Android obsługuje wszystkie funkcje języka Java 7 i podzbiór funkcji języka Java 8, które różnią się w zależności od wersji platformy. Ta strona opisuje nowe funkcje językowe, których możesz użyć, jak poprawnie skonfigurować projekt, aby z nich korzystać oraz wszelkie znane problemy, które możesz napotkać.
Java 8 zawiera podzbiór w Retrolambda
Retrolambda pozwala uruchamiać kod Java 8 z wyrażeniami lambda, referencjami metod i instrukcjami try-with-resources w Javie 7, 6 lub 5. Robi to poprzez przekształcenie kodu bajtowego skompilowanego w Javie 8, tak aby mógł działać na starszym środowisku uruchomieniowym Java.
Funkcje językowe:
Wyrażenia lambda są przenoszone przez konwersję do anonimowych klas wewnętrznych. Obejmuje to optymalizację użycia instancji singleton dla bezstanowych wyrażeń lambda, aby uniknąć powtarzania alokacji obiektów. Odniesienia do metod są w zasadzie tylko cukrem składniowym dla wyrażeń lambda i są importowane w ten sam sposób.
Instrukcje try-with-resources są przenoszone z powrotem przez usunięcie wywołań do
Throwable.addSuppressed
jeśli docelowa wersja kodu bajtowego jest niższa niż Java 7. Jeśli chcesz, aby pominięte wyjątki były rejestrowane zamiast połykane, utwórz żądanie funkcji, a my to zrobimy konfigurowalny.Objects.requireNonNull
są zastępowane wywołaniamiObject.getClass
jeśli docelowa wersja kodu bajtowego jest poniżej Java 7. Syntetyczne kontrole zerowe generowane przez JDK 9 używająObjects.requireNonNull
, podczas gdy wcześniejsze wersje JDK używałyObject.getClass
.Opcjonalnie również:
Metody domyślne są importowane przez kopiowanie metod domyślnych do klasy towarzyszącej (nazwa interfejsu + „$”) jako metody statyczne, zastępowanie metod domyślnych w interfejsie metodami abstrakcyjnymi oraz dodawanie niezbędnych implementacji metod do wszystkich klas, które implementują ten interfejs .
Metody statyczne w interfejsach są importowane przez przeniesienie metod statycznych do klasy towarzyszącej (nazwa interfejsu + „$”) oraz przez zmianę wszystkich wywołań metod w celu wywołania nowej lokalizacji metody.
Znane ograniczenia:
Nie backportuje API Java 8
Domyślne metody tworzenia backportów i metody statyczne na interfejsach wymagają wszystkich backportowanych interfejsów i wszystkich klas, które je implementują lub wywołują swoje metody statyczne, aby były backportowane razem, z jednym wykonaniem Retrolambda. Innymi słowy, zawsze musisz wykonać czystą kompilację. Ponadto, domyślne metody backportowania nie będą działać ponad granicami modułu lub zależności.
Może się zepsuć, jeśli przyszła kompilacja JDK 8 przestanie generować nową klasę dla każdego
invokedynamic
połączeniainvokedynamic
. Retrolambda działa tak, że przechwytuje kod bajtowy generowany przezjava.lang.invoke.LambdaMetafactory
dynamicznie, więc optymalizacja tego mechanizmu może przerwać Retrolambda.
Wtyczka stopni Retrolambda automatycznie zbuduje twój projekt Androida z Retrolambda. Najnowsza wersja znajduje się na stronie wydań .
Stosowanie:
- Pobierz i zainstaluj jdk8
- Dodaj następujące elementy do swojego
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
}
}
Znane problemy:
Lint nie działa na plikach Java, które mają lambdas. Strumień Androida nie rozumie składni java 8 i zawiedzie cicho lub głośno. Istnieje teraz eksperymentalny widelec, który rozwiązuje ten problem.
Korzystanie z usług Google Play powoduje awarię Retrolambda. Wersja 5.0.77 zawiera kod bajtowy, który jest niezgodny z Retrolambda. Powinno to zostać naprawione w nowszych wersjach usług odtwarzania, jeśli możesz je zaktualizować, powinno to być preferowane rozwiązanie. Aby obejść ten problem, możesz użyć wcześniejszej wersji, takiej jak 4.4.52, lub dodać
-noverify
do argumentów-noverify
.
retrolambda {
jvmArgs '-noverify'
}