Особенности языка Ява 7 с Андроидом


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

8 185

8 ответов:

если вы используете 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 и другие javac на основе IDEs поддерживает компиляцию в Android и вы можете установить соответствие даже до Java 8 с помощью:

  • файл → структура проекта → модули → (выберите модуль на 2-й панели) → уровень языка → (выберите "7.0 - алмазы, ARM, multi-catch и т. д.")

Enabling Java 7 on IntelliJ

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

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

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

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

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

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

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

  • исключение цепочки конструкторов в ConcurrentModificationException, LinkageError и AssertionError
  • статический .compare () методы для примитивов: Boolean.compare (), Byte.сравнивать(), Короткий.сравнить(), характер.compare (), целое число.сравните (), долго.сравнение.)(
  • валюты: .getAvailableCurrencies (),.getDisplayName() (а без .getNumericCode ())
  • BitSet: .previousSetBit (),.previousClearBit (),.valueOf (),.toLongArray (),.toByteArray()
  • коллекции: .emptyEnumeration (),.опорожнитель(), .emptyListIterator ()
  • AutoCloseable
  • Throwable: .addSuppressed (),.getSuppressed () и конструктор с 4 аргументами
  • символ: .сравнение. ,)(isSurrogate (),.getName (),.highSurrogate (),.lowSurrogate (),.isBmpCodePoint () (но без .isAlphabetic () and .isIdeographic ())
  • система: .lineSeparator() (без документов?)
  • java.ленг.отражать.Модификатор: .classModifiers (),.constructorModifiers (),.fieldModifiers (),.interfaceModifiers (),.methodModifiers ()
  • NetworkInterface: .getIndex (),.getByIndex()
  • InetSocketAddress: .getHostString ()
  • InetAddress: .getLoopbackAddress ()
  • регистратор: .getGlobal()
  • ConcurrentLinkedDeque
  • AbstractQueuedSynchronizer: .hasQueuedPredecessors ()
  • DeflaterOutputStream: 3 конструктора с "syncFlush".
  • Deflater: .NO_FLUSH, .SYNC_FLUSH, .FULL_FLUSH, .deflate() с 4 аргументами

это в основном все. В частности, NIO 2.0 не существует, а массивы.asList все еще нет @SafeVarargs.

EDIT: в то время, когда это было написано, последним релизом был Android 9 и Eclipse Indigo. С тех пор все изменилось.

  • практический ответ

Да, я пробовал. Но это не большой тест, поскольку совместимость была ограничена уровнем 6 без возможности (по крайней мере, не простой способ) действительно использовать java 7:

  • сначала я установил JDK7 на машине, на которой не был установлен другой JDK-Eclipse и Android также не установлены:

The 7 is the only installed on this machine

  • затем я установил новый Eclipse Indigo и проверил, что он действительно использует JDK 7 (Ну, поскольку это единственный, и поскольку это тот, который я выбрал, я был бы удивлен)

The 7 is the only used by this Eclipse

  • затем я установил последнюю версию Android SDK (EDIT: Honeycomb, API13, в то время как этот пост был написан). Он нашел мой JDK 7 и установлен правильно. То же самое для ADT.

  • но у меня был сюрприз при попытке скомпилировать и запустить приложение Hello Word для Android. Совместимость была установлена на Java 6 без возможности принудительно установить ее на Java 7:

Compatibility is limited to Java 6

  • я попробовал с проектом не Android, обычным Java, и у меня было объяснение. Уровень совместимости, по-видимому, ограничен Eclipse (см. сообщение внизу следующего изображение):

Eclipse limits itself to level 6 compatibility

так у меня было Привет, Мир работа, а также другие приложения, более сложные и с помощью SQLite,Listview,Sensor и Camera, но это только доказывает, что обработка совместимости Java 7, кажется, хорошо сделано и работает с Android.

Итак, кто-то пытался с добрым старым муравьем, чтобы обойти ограничение затмения, замеченное выше?

  • Theroetical ответ

в любом случае, SDK предназначен для использования С Java 5 или 6, как объяснено здесь.

у нас может быть что-то работающее с Java 7, но это будет работать "случайно". Здание DEX может работать правильно или нет, и как только DEX построен, он может работать или нет. Это потому, что использование неквалифицированного JDK дает непредсказуемые результаты по определению.

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

для тех, кто участвует в разработке webapps, это точно так же, как развертывание веб-приложения, построенного под Java 5 или 6 под сервером приложений, квалифицированным только для Java 4 (например, Weblogic 8). Это может работать, но это не то, что может быть рекомендовано для других цели, чем пытаться.

цитата из dalvikvm.com:

dx, включенный в Android SDK, преобразует файлы классов Java классов Java, скомпилированных обычным компилятором Java, в другой формат файла класса (the .формат dex)

Это означает, что .исходный файл Java не имеет значения, это только .байт-код класса.

насколько я знаю, только invokedynamic был добавлен в байт-код JVM в Java 7, остальное совместимо с Java 6. ява сам язык не использует invokedynamic. Другие новые функции, такие как switch заявление строкаs или мульти -лови являются просто синтаксическим сахаром и не требуют изменения байтового кода. Например, мульти-лови просто копирует лови-блок для каждого возможного исключения.

единственная проблема должна быть в том, что новые классы, введенные в Java 7, отсутствуют в Android, например AutoCloseable, поэтому я не уверен, что вы можете использовать попробовать-функция с ресурсами (кто-то пробовал?).

какие-нибудь комментарии по этому поводу? Я что-то упустил?

начиная с Android SDK v15, наряду с Eclipse 3.7.1, Java 7 является не поддерживается для разработки Android. Установка совместимости источника на 1.7 мандаты установка сгенерированного .класс совместимости файлов до 1.7, что приводит к следующей ошибке компилятора Android:

Android требует уровень соответствия компилятора 5.0 или 6.0. Нашли '1.7' вместо этого. Пожалуйста, используйте инструменты Android > исправить свойства проекта.

чтобы расширить приведенный выше ответ @KennyTM, если вы нацелены на 4.0.3 и выше (minSdkVersion=15), вы можете использовать скрытые API, добавив несколько классов в SDK вашего целевого android.сосуд.

как только вы это сделаете, вы можете использовать try-with-resources на любом закрытом, а также реализовать автоклавирование в своих собственных классах.

Я сделал zip, содержащий источники и двоичные файлы всех классов, которые необходимо было изменить в android.jar, чтобы сделать эти API доступный. Вам просто нужно распаковать его и добавить двоичные файлы в ваш
android-sdk / платформы / android-NN / android.банку

вы можете скачать его здесь:http://db.tt/kLxAYWbr

также следует отметить, что за последние пару месяцев Эллиот Хьюз сделал несколько коммитов для дерева Android:добили AutoCloseable,добавлено SafeVarargs,unhidden различные API,исправлено Защищенный конструктор Throwable и добавлена поддержка файлов класса версии 51 в dx. Итак, наконец-то есть некоторый прогресс.

Edit (Апрель 2014):

С выпуском SDK 19 больше не нужно исправлять android.jar с дополнительными API.

лучший способ использовать try-with-resources в Android Studio для приложения, предназначенного для 4.0.3 и выше (minSdkVersion=15) - добавить после compileOptions на build.gradle:

android {
    compileSdkVersion 19
    buildToolsVersion '19.0.3'

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 19
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

Android Studio будет жаловаться, что try-with-resources не может использоваться с этим уровнем API, но мой опыт заключается в том, что он может. Проект будет построен и запущен без проблем на устройствах с 4.0.3 и выше. Я не испытывал никаких проблем с этим, с приложением, которое было установлено в 500k+ устройств.

Android Studio error

чтобы игнорировать это предупреждение, добавьте следующее в lint.xml:

<issue id="NewApi">
    <ignore regexp="Try-with-resources requires API level 19"/>
</issue>

кажется, что заставить это работать с чистым муравьем-это немного Клудж.

но это сработало для меня: http://www.informit.com/articles/article.aspx?p=1966024

чтобы использовать функции Java 7 в сборке кода системой сборки на основе ant Android, просто поместите следующее в свой custom_rules.xml в корневом каталоге вашего проекта:

custom_rules.XML-код:

<project name="custom_android_rules">
    <property name="java.target" value="1.7" />
    <property name="java.source" value="1.7" />
</project>

некоторые люди могут быть заинтересованы в этом проекте git, который я нашел, что, кажется, позволяет запускать Java 7 на android. https://github.com/yareally/Java7-on-Android

однако слишком большой риск, если я добавлю это в текущий проект, над которым я работаю. Поэтому я подожду, пока Google официально не поддержит Java 7.