Особенности языка Java 7 с Android - PullRequest
188 голосов
/ 23 августа 2011

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

Ответы [ 8 ]

164 голосов
/ 25 ноября 2012

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

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

Enabling Java 7 on IntelliJ

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

  • Оператор Diamond (<>)
  • Строковый переключатель
  • Множественный улов (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».
  • Deflater : .NO_FLUSH, .SYNC_FLUSH, .FULL_FLUSH, .deflate () с 4 аргументами

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

70 голосов
/ 24 августа 2011

РЕДАКТИРОВАТЬ: на момент написания этой статьи, последний релиз был Android 9 и Eclipse Indigo.С тех пор все изменилось.

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

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

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

The 7 is the only installed on this machine

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

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

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

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

  • Теоретический ответ

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

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

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

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

38 голосов
/ 03 ноября 2011

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

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

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

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

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

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

12 голосов
/ 19 ноября 2011

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

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

5 голосов
/ 26 июня 2013

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

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

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

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

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

Редактировать (апрель 2014 г.):

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

Лучший способ использовать try-with-resources в Android Studio для приложения с версией 4.0.3 и выше ( minSdkVersion = 15 ) - добавить следующий compileOptions to 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>
1 голос
/ 07 июля 2014

Чтобы использовать функции Java 7 при сборке кода с помощью системы сборки 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>
1 голос
/ 01 июля 2013

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

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

0 голосов
/ 13 мая 2013

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

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

...