Просто интересно, попробовал ли кто-нибудь использовать новые функции языка Java 7 с Android? Я знаю, что Android читает байт-код, который Java выплевывает и превращает его в dex. Поэтому, я думаю, мой вопрос в том, может ли он понять байт-код Java 7?
Java-язык с поддержкой Android
Ответ 1
Если вы используете Android Studio, язык Java 7 должен быть включен автоматически без каких-либо патчей. Для Try-with-resource требуется API-уровень 19+, а материал NIO 2.0 отсутствует.
Если вы не можете использовать функции Java 7, см. @Nuno ответ на вопрос о том, как отредактировать build.gradle
.
Ниже приводится только исторический интерес.
Небольшая часть Java 7, безусловно, может использоваться с Android (примечание: я тестировал только 4.1).
Прежде всего, вы не можете использовать Eclipse ADT, потому что жестко закодировано, что совместимы только Java-компилятор 1.5 и 1.6. Вы можете перекомпилировать ADT, но я считаю, что нет простого способа сделать это, кроме перекомпиляции всего Android вместе.
Но вам не нужно использовать Eclipse. Например, Android Studio 0.3.2, IntelliJ IDEA CE и другие java-совместимые IDE файлы поддерживают компиляцию на Android и, вы можете установить соответствие даже с Java 8 с помощью
- Файл → Структура проекта → Модули → (выберите модуль на второй панели) → Уровень языка → (выберите "7.0 - Алмазы, ARM, многопользовательский захват и т.д." )
Это позволяет использовать возможности языка 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().
- Currency:.getAvailableCurrencies(),.getDisplayName() (но без .getNumericCode())
- BitSet:.previousSetBit(),.previousClearBit(),.valueOf(),.toLongArray(),.toByteArray( )
- Collections:.emptyEnumeration(),.emptyIterator(),.emptyListIterator()
- AutoCloseable
- Throwable:.addSuppressed(),.getSuppressed() и конструктор с 4 аргументами
- Character:.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.
Ответ 2
EDIT: В то время, когда это было написано, последней версией были Android 9 и Eclipse Indigo. С тех пор ситуация изменилась.
- Практический ответ
Да, я пробовал. Но это не отличный тест, так как совместимость была ограничена уровнем 6 без возможности (по крайней мере, простой способ) использовать java 7:
- Сначала я установил JDK7 на машине, у которой не было другого JDK, установленного - Eclipse и Android также не установлены:
- Затем я установил совершенно новый Eclipse Indigo и проверил, что на самом деле он использует JDK 7 (ну, так как это единственный, и поскольку это тот, который я выбрал, я был бы удивлен)
-
Затем я установил последнюю версию Android SDK (EDIT: Honeycomb, API13, на момент написания этой статьи). Он нашел мой JDK 7 и установлен правильно. То же самое для ADT.
-
Но у меня был сюрприз при попытке скомпилировать и запустить приложение Hello Word для Android. Совместимость была установлена на Java 6 без возможности принудительного перехода на Java 7:
- Я пробовал с проектом, отличным от Android, обычным Java, и у меня было объяснение. Уровень совместимости, по-видимому, ограничен Eclipse (см. Сообщение внизу нижеследующего изображения):
Таким образом, у меня был Hello World, а также другие приложения, более сложные и с использованием SQLite
, Listview
, Sensor
и Camera
, но это только доказывает, что обработка совместимости Java 7 выглядит хорошо и работает с Android.
Итак, кто-то пытался с добрым старым Ant, чтобы обойти ограничение Eclipse, увиденное выше?
- Теоретический ответ
В любом случае, SDK предназначен для использования с Java 5 или 6, как описано здесь.
У нас может быть что-то работающее с Java 7, но оно будет работать "случайно". Здание DEX может работать нормально или нет, и как только DEX будет построен, он может работать или нет. Это связано с тем, что использование неквалифицированного JDK дает непредсказуемые результаты по определению.
Даже если кто-то успешно создал Android-приложение под простой Java 7, это не относится к JDK. Тот же процесс, применяемый к другому приложению, может завершиться неудачей, или в результате приложения могут возникнуть ошибки, связанные с использованием этого JDK. Не рекомендуется.
Для тех, кто участвует в разработке webapps, это точно так же, как развертывание веб-приложения, созданного под Java 5 или 6 под сервером приложений, доступным только для Java 4 (например, Weblogic 8). Это может сработать, но это не то, что можно рекомендовать для других целей, чем пытаться.
Ответ 3
Цитата из dalvikvm.com:
dx, включенный в Android SDK, преобразует файлы классов Java классов Java, скомпилированные обычным компилятором Java в другой формат файла классов (формат .dex)
Это означает, что исходный файл .java не имеет значения, это только байт-код .class.
Насколько я знаю, в JTM-код JVM в Java 7 добавлен только invokedynamic, остальное совместимо с Java 6. Сам язык Java не использует invokedynamic. Другие новые функции, такие как оператор switch с использованием String s или multi- catch, являются просто синтаксическим сахаром и не требуют изменений байтового кода. Например, multi- catch просто копирует catch -block для каждого возможного исключения.
Единственная проблема заключается в том, что новые классы, введенные в Java 7, отсутствуют в Android, например AutoCloseable, поэтому я не уверен, что вы можете использовать try -with-resources (кто-то пробовал?).
Любые комментарии по этому поводу? Я что-то пропустил?
Ответ 4
Начиная с Android SDK v15, наряду с Eclipse 3.7.1, Java 7 поддерживает не для разработки Android. Настройка совместимости источника с 1.7 мандатами, устанавливающая сгенерированную совместимость файла .class с номером 1.7, что приводит к следующей ошибке компилятора Android:
Для Android требуется уровень соответствия компилятора 5.0 или 6.0. Вместо этого найдено "1.7". Используйте Android Tools > Fix Project Properties.
Ответ 5
Чтобы расширить этот ответ от @KennyTM, если вы используете таргетинг 4.0.3 и выше (minSdkVersion = 15), вы можете использовать скрытые API, добавив несколько классов в целевой SDK android.jar.
Как только вы сделаете это, вы можете использовать try-with-resources для любого Closeable, а также реализовать AutoCloseable в своих собственных классах.
Я сделал zip, содержащий источники и двоичные файлы всех классов, которые необходимо было изменить в android.jar, чтобы сделать эти API доступными. Вам просто нужно распаковать его и добавить двоичные файлы в ваш файл android-sdk/platform/android-NN/android.jar
Вы можете скачать его здесь: http://db.tt/kLxAYWbr
Также следует отметить, что за последние пару месяцев Эллиотт Хьюз сделал несколько коммитов для дерева Android: закончил AutoCloseable, добавил SafeVarargs, скрытые различные API, fixed Throwable protected constructor и добавлена поддержка файлов классов версии 51 в dx. Итак, наконец-то начался определенный прогресс.
Изменить (апрель 2014):
С выпуском SDK 19 больше не нужно исправлять файл android.jar с дополнительными API-интерфейсами.
Лучший способ использовать try-in-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 +.
Чтобы игнорировать это предупреждение, добавьте следующее в свой lint.xml
:
<issue id="NewApi">
<ignore regexp="Try-with-resources requires API level 19"/>
</issue>
Ответ 6
Кажется, что заставить работать работать с чистым ant является битком.
Но это сработало для меня: http://www.informit.com/articles/article.aspx?p=1966024
Ответ 7
Чтобы использовать функции 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>
Ответ 8
Некоторые люди могут быть заинтересованы в этом проекте git, который я нашел, что позволяет запускать Java 7 на Android. https://github.com/yareally/Java7-on-Android
Однако слишком большой риск, если я добавлю это в текущий проект, над которым я работаю. Поэтому я подожду, пока Google официально не поддержит Java 7.