Особенности языка Java 7 с Android

188

Просто интересно, пытался ли кто-нибудь использовать новые функции языка Java 7 с Android? Я знаю, что Android читает байт-код, который выплевывает Java, и превращает его в dex. Итак, я думаю, мой вопрос, может ли он понять байт-код Java 7?

Даниэль Райан
источник
10
В качестве альтернативы, может быть, вы можете использовать функции языка Java 7, но компилировать в байт-код Java 6?
MatrixFrog
2
Android Studio теперь выдаст вам уведомление при создании нового проекта: «С minSdkVersion менее 19 вы не можете использовать try-with-resources, но другие функции языка Java 7 хороши»
IgorGanapolsky
1
Да, я знаю :) Мы наконец-то используем Java 7 в нашем проекте.
Даниэль Райан

Ответы:

165

Если вы используете Android Studio , то Java 7 язык должен быть включен автоматически , без каких - либо исправлений. Try-with-resource требует API уровня 19+, а NIO 2.0 не хватает.

Если вы не можете использовать функции Java 7, см. Ответ @Nuno о том, как отредактировать свой build.gradle.

Следующее только для исторического интереса.


Небольшая часть Java 7, безусловно, может использоваться с Android (примечание: я тестировал только на 4.1).

Прежде всего, вы не могли использовать ADT Eclipse, потому что он жестко запрограммирован на совместимость только с Java-компиляторами 1.5 и 1.6. Вы можете перекомпилировать ADT, но я считаю, что нет простого способа сделать это, кроме перекомпиляции всего Android вместе.

Но вам не нужно использовать Eclipse. Например, Android Studio 0.3.2 , IntelliJ IDEA CE и другие IDE на основе javac поддерживают компиляцию под Android, и вы можете установить соответствие даже до Java 8 с помощью:

  • Файл → Структура проекта → Модули → (выберите модуль на 2-й панели) → Уровень языка → (выберите «7.0 - Бриллианты, ARM, мульти-улов и т. Д.»)

Включение Java 7 в IntelliJ

Это позволяет использовать только функции языка Java 7 , и вы вряд ли сможете извлечь выгоду из чего-либо, поскольку половина улучшений также обеспечивается библиотекой. Возможности, которые вы можете использовать, это те, которые не зависят от библиотеки:

  • Алмазный оператор ( <>)
  • Струнный переключатель
  • Множественный улов ( catch (Exc1 | Exc2 e))
  • Подчеркивать в числовых литералах ( 1_234_567)
  • Двоичные литералы ( 0b1110111)

И эти функции не могут быть использованы еще :

  • Оператор try-with-resources - потому что он требует несуществующего интерфейса "java.lang.AutoCloseable" (это можно использовать публично в 4.4+)
  • Аннотация @SafeVarargs - потому что "java.lang.SafeVarargs" не существует

... "пока" :) Оказывается, что, хотя библиотека Android ориентирована на 1.6, источник Android содержит интерфейсы, такие как AutoCloseable, и традиционные интерфейсы, такие как Closeable , наследуют от AutoCloseable (хотя SafeVarargs действительно отсутствует). Мы могли бы подтвердить его существование через отражение. Они скрыты просто потому, что в Javadoc есть @hideтег, из-за которого «android.jar» не включает их.

Уже существует уже существующий вопрос Как мне собрать Android SDK со скрытыми и доступными внутренними API? о том, как вернуть эти методы. Вам просто нужно заменить существующую ссылку «android.jar» текущей Платформы на нашу настроенную, после чего станут доступны многие API Java 7 (процедура аналогична той, что в Eclipse. Проверьте Структуру проекта → SDK.)

В дополнение к AutoCloseable, (только) также раскрываются следующие функции библиотеки Java 7 :

  • Конструкторы цепочки исключений в ConcurrentModificationException, LinkageError и AssertionError
  • Статические методы .compare () для примитивов: Boolean.compare (), Byte.compare (), Short.compare (), Character.compare (), Integer.compare (), Long.compare ().
  • Валюта : .getAvailableCurrencies (), .getDisplayName () (но без .getNumericCode ())
  • BitSet : .previousSetBit (), .previousClearBit (), .valueOf (), .toLongArray (), .toByteArray ()
  • Коллекции : .emptyEnumeration (), .emptyIterator (), .emptyListIterator ()
  • AutoCloseable
  • Throwable : .addSuppressed (), .getSuppressed () и конструктор с 4 аргументами.
  • Характер : .compare (), .isSurrogate (), .getName (), .highSurrogate (), .lowSurrogate (), .isBmpCodePoint () (но без .isAlphabetic () и .isIdeographic ())
  • Система: .lineSeparator () (без документов?)
  • java.lang.reflect.Modifier : .classModifiers (), .constructorModifiers (), .fieldModifiers (), .interfaceModifiers (), .methodModifiers ()
  • NetworkInterface : .getIndex (), .getByIndex ()
  • InetSocketAddress : .getHostString ()
  • InetAddress : .getLoopbackAddress ()
  • Logger : .getGlobal ()
  • ConcurrentLinkedDeque
  • AbstractQueuedSynchronizer : .hasQueuedPredecessors ()
  • DeflaterOutputStream : 3 конструктора с «syncFlush».
  • Дефлятор : .NO_FLUSH, .SYNC_FLUSH, .FULL_FLUSH, .deflate () с 4 аргументами

Это в основном все. В частности, NIO 2.0 не существует, а Arrays.asList все еще не является @SafeVarargs.

kennytm
источник
2
Отличный ответ. Я надеюсь, что полная поддержка на уровне jvm произойдет в ближайшее время, nio2и другие плюсы определенно будут хорошей новостью.
SD
4
Стоит отметить, что AutoCloseableинтерфейс не существует во время выполнения Android до ICS (или, возможно, до HoneyComb). Так что даже если вы используете исправленный android.jar, вы получите NoClassDefFoundErrorсистему 2.x.
Идолон
2
@deviant: для этого требуется изменить виртуальную машину Dalvik, поскольку в Java 8 используется лямбда, invokedynamicкоторая не поддерживается JVM, ориентированной на Java 6.
kennytm
2
Возможно, вы захотите добавить обновление, которое, начиная с Android Studio 3.2, полностью поддерживает языковой уровень 7, как и
пробная версия
4
попробовать с ресурсами теперь можно использовать на SDK 19 (Android Kitkat). см. tools.android.com/recent/androidstudio032released
Мохаммед Эль-Накиб,