Особливості мови Java 7 за допомогою Android


188

Мені цікаво, чи хтось намагався використовувати нові функції Java 7 з Android? Я знаю, що Android читає байт-код, який виплює Java, і перетворює його в dex. Тож я гадаю, що моє запитання: чи може він зрозуміти байт-код Java 7?


10
Або, можливо, ви можете використовувати мовні функції Java 7, але компілювати в байт-код Java 6?
MatrixFrog

2
Android Studio тепер надасть вам сповіщення при створенні нового проекту: "Якщо minSdkVersion менше 19, ви не можете користуватися
пробними

1
Так, я знаю :) Ми нарешті використовуємо Java 7 в нашому проекті.
Даніель Райан

Відповіді:


165

Якщо ви використовуєте Android Studio , мова Java 7 повинна бути включена автоматично, без патчів. Для випробування ресурсу потрібен рівень 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

Це дозволяє лише мови мови 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.)

Окрім функції автоматичного закриття, (лише) розкриваються також такі функції бібліотеки 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 ()
  • Автозакриття
  • Throwable : .addSuppression (), .getSuppression () та конструктор 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.


2
Чудова відповідь. Я сподіваюся, що в майбутньому незабаром відбудеться повна підтримка рівня jvm, nio2а інші смаколики, безумовно, будуть хорошою новиною.
SD

4
Варто зазначити, що AutoCloseableінтерфейс не існує в режимі виконання Android до ICS (або, можливо, до HoneyComb). Тож навіть якщо ви користуєтеся виправленим android.jar, ви отримаєте NoClassDefFoundErrorв системі 2.x.
Ідолон

2
@deviant: Для цього потрібна модифікація Dalvik VM, оскільки Java 8 використовує лямбда, invokedynamicяка не підтримується JVM, орієнтованою на Java 6.
kennytm

2
Ви можете додати оновлення, що для Android студії 3.2 мова 7 рівня повністю підтримується, як і
пробні

4
спробуйте ресурси тепер можна використовувати на SDK 19 (Android Kitkat). дивіться tools.android.com/recent/androidstudio032Опубліковано
Мохамед Ель-Накіб

70

EDIT: На момент написання цього запису останній реліз був Android 9 та Eclipse Indigo. З того часу все змінилося.

  • Практична відповідь

Так, я спробував. Але це не чудовий тест, оскільки сумісність була обмежена до рівня 6, оскільки жодним простим способом не можна використовувати Java 7:

  • Спершу я встановив JDK7 на машину, на якій не було встановлено інших JDK - Eclipse та Android також не встановлені:

7 є єдиним встановленим на цій машині

  • Тоді я встановив абсолютно новий Eclipse Indigo і перевірив, чи він насправді використовує JDK 7 (ну, оскільки це єдиний і, як це я вибрав, я був би здивований)

7 - це єдине, що використовується цим Затемненням

  • Тоді я встановив останню версію Android SDK (EDIT: Honeycomb, API13, на момент написання цієї публікації). Він знайшов мій JDK 7 та встановлений належним чином. Те саме для ADT.

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

Сумісність обмежена Java 6

  • Я спробував з проектом, який не є Android, звичайним Java, і мені було пояснення. Здається, рівень сумісності обмежений програмою Eclipse (див. Повідомлення внизу наступного зображення):

Eclipse обмежує себе на рівні 6 сумісності

Так що я був 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). Це може спрацювати, але це не те, що можна рекомендувати для інших цілей, ніж намагатися.


1
Дякуємо за детальний огляд. Так виглядає, що ви не можете використовувати функції мови 7, але все ще використовуєте Java 7 як Java 6. Сподіваємось, це скоро зміниться :)
Даніель Раян,

Це з Eclipse. З Мурашкою це, мабуть, можливо. Я сподіваюся, що хтось зробить тест, і я звинувачую себе в тому, що я лінивий робити це :)
Шлублу,

Так, Варга, але я не думаю, що обмеження версії компілятора походить від Ant, а не від Eclipse.
Шлублу

2
Також зауважте, що якщо ви граєте з декількома версіями Java, надані інструменти не сумісні. Я маю на увазі те, що якщо ви спершу підписали додаток з jarsigner від інструментів java 6, а потім встановили java 7 і підписали нову версію нашого додатку з jarsigner, що постачається з java 7, і тим самим сховищем ключів, що і раніше підписи не збігалися !
Тимо

38

Цитата від dalvikvm.com:

dx, що входить до Android SDK, перетворює файли класів Java класів Java, складені звичайним компілятором Java, у інший формат файлу класу (формат .dex)

Це означає, що вихідний файл .java не має значення, це лише байт-код .class.

Наскільки я знаю, до байт-коду JVM на Java 7 додано лише викликаний динамік , решта сумісна з Java 6. Сама мова Java не використовує анкідінамічну . Інші нові функції, такі як оператор перемикання за допомогою String s або multi- catch - це лише синтатичний цукор і не потребують змін байтового коду. Наприклад, multi- catch просто копіює блок- catch для кожного можливого винятку.

Єдина проблема повинна полягати в тому, що нові класи, представлені в Java 7, відсутні в Android, як-от AutoCloseable , тому я не впевнений, чи можете ви скористатися функцією try -with-ресурси (хтось спробував це?).

Будь-які коментарі до цього? Я щось пропускаю?


2
Тепер проблема полягає в тому, як ми можемо налаштувати так, щоб вихідні коди Java 7 збиралися у файли класу Java 6, особливо в затемненні?
Ренді Сугіанто 'Юку'

Залишилося єдине питання - чому ви навіть турбуєтесь?
Warpzit

@Warpzit, головне питання має бути: Чому розробник не буде турбуватися за всю цю плутанину?
Аміт

@Amit тому, що він зрозумів, що Android відрізняється від Java, і для роботи з Android він повинен використовувати запропоновані інструменти.
Warpzit

2
@Warpzit Єдине його запитання: " Чи може Android зрозуміти Java 7? " Невігластво ніколи не є рішенням / відповіддю ...
Amit

12

Що стосується 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

Щоб розгорнути вищевказану відповідь від @KennyTM, якщо ви орієнтуєтесь на версію 4.0.3 і вище ( minSdkVersion = 15 ), ви можете використовувати приховані API, додавши кілька класів до SDK android.jar вашої цілі.

Як тільки ви це зробите, ви можете користуватися пробними ресурсами на будь-якому Closeable, а також реалізовувати AutoCloseable у власних класах.

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

Завантажити його можна звідси: http://db.tt/kLxAYWbr

Також слід зазначити, що за останні пару місяців Елліотт Х'юз зробив кілька зобов’язань для дерева Android: завершив функцію автоматичного зачинення , додав SafeVarargs , відкрив різні API , виправив захищений конструктор Throwable та додав підтримку файлів класу версії 51 у dx . Тож, нарешті, деякий прогрес відбувається.

Редагувати (квітень 2014 р.):

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

Кращий спосіб використання примірочних з-ресурсів в 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 поскаржиться, що пробні ресурси не можна використовувати з цим рівнем API, але мій досвід полягає в тому, що він може. Проект буде створюватися і працювати без проблем на пристроях з версією 4.0.3 і вище. У мене не виникло жодних проблем із цим додатком, встановленим на пристрої 500k +.

Помилка Android Studio

Щоб ігнорувати це попередження, додайте до свого lint.xml:

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

1
Мені здається цікавим те, що попередження про код Android Studio говорить про те, що "пробні ресурси" є новими в API 13, і я повинен використовувати його. Хоча насправді не встигають перевірити, чи працює він правильно.
Даніель Райан

1

Здається, що змусити це працювати з чистими мурахами - це чимось хитрощі.

Але це працювало для мене: http://www.informit.com/articles/article.aspx?p=1966024


1
Я довго це шукав. Щоб вирішити проблеми з людьми через фільтрування статті, вам потрібно буде змінити рядок `<властивість = =" java.source "value =" 1.5 "/>` у build.xml, який надає android (не той, що в ваш проект!). Для мене це було в /opt/android-sdk-update-manager/tools/ant/build.xml
Матеуш Ковальчик

Ні, ти цього не робиш. Ви можете перезаписати ці властивості custom_rules.xml, дивіться мою відповідь тут: stackoverflow.com/a/24608415/194894
Потік

1

Для того, щоб використовувати функції 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>

0

Деяких людей може зацікавити цей проект git, який я знайшов, і, здається, дозволяє запускати Java 7 на android. https://github.com/yareally/Java7-on-Android

Однак занадто великий ризик, якщо я додам це до поточного проекту, над яким я працюю. Тож я зачекаю, поки Google офіційно підтримає Java 7.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.